home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 February / EnigmA AMIGA RUN 15 (1997)(G.R. Edizioni)(IT)[!][issue 1997-02][PLANET CD V].iso / enigma / earcd / varie / uae-0_64.lha / uae-0.6.4 / src / compiler.c < prev    next >
C/C++ Source or Header  |  1996-09-10  |  103KB  |  3,612 lines

  1.  /* 
  2.   * UAE - The Un*x Amiga Emulator
  3.   * 
  4.   * m68k emulation
  5.   *
  6.   * (c) 1995 Bernd Schmidt
  7.   */
  8.  
  9. #include "sysconfig.h"
  10. #include "sysdeps.h"
  11.  
  12. #include "config.h"
  13. #include "options.h"
  14. #include "events.h"
  15. #include "gui.h"
  16. #include "memory.h"
  17. #include "custom.h"
  18. #include "newcpu.h"
  19. #include "ersatz.h"
  20. #include "readcpu.h"
  21. #include "blitter.h"
  22. #include "debug.h"
  23. #include "autoconf.h"
  24. #include "compiler.h"
  25.  
  26. #define RELY_ON_LOADSEG_DETECTION
  27.  
  28. #ifdef USE_COMPILER
  29.  
  30. #include <sys/mman.h>
  31.  
  32. char *address_space, *good_address_map;
  33.  
  34. code_execfunc exec_me;
  35. UBYTE nr_bbs_to_run = 1;
  36. int nr_bbs_start = 40;
  37.  
  38. static int compile_failure;
  39. static int quiet_compile = 1;
  40. int i_want_to_die = 1;
  41. static int n_compiled = 0;
  42. static int n_max_comp = 99999999;
  43. static CPTR call_only_me = 0;
  44.  
  45. int patched_syscalls = 0;
  46.  
  47. static int count_bits(UWORD v)
  48. {
  49.     int bits = 0;
  50.     while (v != 0) {
  51.     if (v & 1)
  52.         bits++;
  53.     v >>= 1;
  54.     }
  55.     return bits;
  56. }
  57.  
  58. static UWORD bitswap(UWORD v)
  59. {
  60.     UWORD newv = 0;
  61.     UWORD m1 = 1, m2 = 0x8000;
  62.     int i;
  63.     
  64.     for (i = 0; i < 16; i++) {
  65.     if (v & m1)
  66.         newv |= m2;
  67.     m2 >>= 1;
  68.     m1 <<= 1;
  69.     }
  70.     return newv;
  71. }
  72.  
  73. static long long compiled_hits = 0;
  74.  
  75. /* @@@ FIXME: a defragmenter would be nice for this, but since we flush
  76.  * the cache all the time anyway to deal with LoadSegs() */
  77.  
  78. /* 16K areas with 512 byte blocks */
  79. #define SUBUNIT_ORDER 9
  80. #define PAGE_SUBUNIT (1 << SUBUNIT_ORDER)
  81. #define PAGE_ALLOC_UNIT (PAGE_SUBUNIT * 32)
  82.  
  83. static int zerofd;
  84. static int zeroff;
  85. static struct code_page *first_code_page;
  86.  
  87. static struct code_page *new_code_page(void)
  88. {
  89.     struct code_page *ncp;
  90.     
  91.     ncp = (struct code_page *)mmap(NULL, PAGE_ALLOC_UNIT, 
  92.                    PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE,
  93.                    zerofd, zeroff);
  94.     zeroff += PAGE_ALLOC_UNIT;
  95.     if (ncp) {
  96.     ncp->next = first_code_page;
  97.     first_code_page = ncp;
  98.     ncp->allocmask = 1; /* what a waste */
  99.     }
  100.     return ncp;
  101. }
  102.  
  103. #define NUM_HASH 1024
  104. #define NUM_FUNCTIONS 8192
  105. #define HASH_MASK (NUM_HASH-1)
  106.  
  107. static int SCAN_MARK = 5; /* Number of calls after which to scan a function */
  108. static int COMPILE_MARK = 50; /* Number of calls after which to compile a function */
  109.  
  110. static struct hash_entry cpu_hash[NUM_HASH];
  111. static struct hash_block lru_first_block;
  112. static struct hash_entry lru_first_hash;
  113. static struct hash_entry *freelist_hash;
  114. static struct hash_block *freelist_block;
  115. static struct hash_entry hash_entries[NUM_FUNCTIONS];
  116.  
  117. static int m68k_scan_func(struct hash_entry *);
  118. static int m68k_compile_block(struct hash_block *);
  119.  
  120. static char *alloc_code(struct hash_block *hb, int ninsns)
  121. {
  122.     struct code_page *cp;
  123.     long int allocsize = (ninsns * 32 + PAGE_SUBUNIT-1) & ~(PAGE_SUBUNIT-1);
  124.     ULONG allocmask;
  125.     int allocbits;
  126.     int j;
  127.     int last_bit;
  128.  
  129.     if (allocsize >= (PAGE_ALLOC_UNIT - (1 << SUBUNIT_ORDER)))
  130.     return NULL;
  131.     allocbits = (allocsize >> SUBUNIT_ORDER);
  132.     allocmask = (1 << allocbits) - 1;
  133.     
  134.     for (cp = first_code_page; cp != NULL; cp = cp->next) {
  135.     ULONG thispage_alloc = cp->allocmask;
  136.     for (j = 1; j < (33 - allocbits); j++) {
  137.         if ((cp->allocmask & (allocmask << j)) == 0) {
  138.         goto found_page;
  139.         }
  140.     }
  141.     }
  142.  
  143.     /* Nothing large enough free: make a new page */
  144.     cp = new_code_page();
  145.     if (cp == NULL)
  146.     return NULL;
  147.     j = 1;
  148.     
  149. found_page:
  150.     /* See whether there is in fact more space for us. If so, allocate all of
  151.      * it. compile_block() will free everything it didn't need. */
  152.  
  153.     allocmask <<= j;
  154.     last_bit = allocbits + j;
  155.     while (last_bit < 32 && (cp->allocmask & (1 << last_bit)) == 0) {
  156.     allocmask |= 1 << last_bit;
  157.     allocsize += PAGE_SUBUNIT;
  158.     last_bit++;
  159.     }
  160.  
  161.     hb->page_allocmask = allocmask;
  162.     hb->cpage = cp;
  163.     cp->allocmask |= allocmask;
  164.     hb->compile_start = ((char *)cp + (j << SUBUNIT_ORDER));
  165.     hb->alloclen = allocsize;
  166.     return hb->compile_start;
  167. }
  168.  
  169. static int remove_hash_from_lists(struct hash_entry *h)
  170. {
  171.     if (h->locked || h->cacheflush)
  172.     return 0;
  173.  
  174.     h->lru_next->lru_prev = h->lru_prev;
  175.     h->lru_prev->lru_next = h->lru_next;
  176.     
  177.     h->next->prev = h->prev;
  178.     h->prev->next = h->next;
  179.     return 1;
  180. }
  181.  
  182. static void forget_block(struct hash_block *hb)
  183. {
  184.     struct hash_entry *h = hb->he_first;
  185.     
  186.     hb->lru_next->lru_prev = hb->lru_prev;
  187.     hb->lru_prev->lru_next = hb->lru_next;
  188.  
  189.     hb->lru_next = freelist_block;
  190.     freelist_block = hb;
  191.  
  192.     if (hb->cpage != NULL)
  193.     fprintf(stderr, "Discarding block with code. Tsk.\n");
  194.  
  195.     do {
  196.     struct hash_entry *next = h->next_same_block;
  197.     h->block = NULL;
  198.     h->execute = NULL;
  199.     h->next_same_block = NULL;
  200.     h = next;
  201.     } while (h != hb->he_first);
  202. }
  203.  
  204. static void kill_lru_block(void)
  205. {
  206.     struct hash_block *hb = lru_first_block.lru_next;
  207.     struct hash_entry *h = hb->he_first;
  208.     
  209.     hb->lru_next->lru_prev = hb->lru_prev;
  210.     hb->lru_prev->lru_next = hb->lru_next;
  211.  
  212.     hb->lru_next = freelist_block;
  213.     freelist_block = hb;
  214.     
  215.     if (hb->cpage != NULL) {
  216.     hb->cpage->allocmask &= ~hb->page_allocmask;
  217.     }
  218.     do {
  219.     struct hash_entry *next = h->next_same_block;
  220.     if (remove_hash_from_lists(h)) {
  221.         h->next_same_block = freelist_hash;
  222.         freelist_hash = h;
  223.     } else {
  224.         h->block = NULL;
  225.         h->next_same_block = NULL;
  226.         h->execute = NULL;
  227.     }
  228.     h = next;
  229.     } while (h != hb->he_first);
  230. }
  231.  
  232. static void lru_touch_block(struct hash_block *h)
  233. {
  234.     h->lru_next->lru_prev = h->lru_prev;
  235.     h->lru_prev->lru_next = h->lru_next;
  236.     
  237.     h->lru_next = &lru_first_block;
  238.     h->lru_prev = lru_first_block.lru_prev;
  239.     h->lru_prev->lru_next = h;
  240.     lru_first_block.lru_prev = h;    
  241. }
  242.  
  243. static int check_block(struct hash_block *hb)
  244. {
  245. #ifndef RELY_ON_LOADSEG_DETECTION
  246.     struct hash_entry *h = hb->he_first;
  247.     
  248.     do {
  249.     struct hash_entry *next = h->next_same_block;
  250.     if (h->matchword != *(ULONG *)get_real_address(h->addr))
  251.         return 0;
  252.     h = next;
  253.     } while (h != hb->he_first);
  254. #endif
  255.     return 1;
  256. }
  257.  
  258. ULONG flush_icache(void)
  259. {
  260.     struct hash_block *hb = lru_first_block.lru_next;
  261.     
  262.     while (hb != &lru_first_block) {
  263.     struct hash_block *next = hb->lru_next;
  264.     if (hb->cpage != NULL) {
  265.         /* Address in chipmem? Then forget about block*/
  266.         if ((hb->he_first->addr & ~0xF80000) != 0xF80000) {
  267.         hb->cpage->allocmask &= ~hb->page_allocmask;
  268.         hb->cpage = NULL;
  269.         forget_block(hb);
  270.         }
  271.     }
  272.     hb = next;
  273.     }
  274.     return regs.d[0];
  275. }
  276.  
  277. void possible_loadseg(void)
  278. {
  279.     fprintf(stderr, "Possible LoadSeg() detected\n");
  280.     flush_icache();
  281. }
  282.  
  283. static struct hash_block *new_block(void)
  284. {
  285.     struct hash_block *b = freelist_block;
  286.     
  287.     if (b != NULL) {
  288.     freelist_block = b->lru_next;
  289.     } else
  290.     b = (struct hash_block *)malloc(sizeof *b);
  291.     b->nrefs = 0;
  292.     b->cpage = NULL;
  293.     b->he_first = NULL;
  294.     b->translated = b->untranslatable = b->allocfailed = 0;
  295.     return b;
  296. }
  297.  
  298. static struct hash_entry *get_free_hash(void)
  299. {
  300.     struct hash_entry *h;
  301.  
  302.     for (;;) {
  303.     h = freelist_hash;
  304.     if (h != NULL) {
  305.         freelist_hash = h->next_same_block;
  306.         break;
  307.     } 
  308.     h = lru_first_hash.lru_next;
  309.     if (h->block == NULL) {
  310.         remove_hash_from_lists(h);
  311.         break;
  312.     }
  313.     kill_lru_block();
  314.     }
  315.     h->block = NULL;
  316.     h->ncalls = 0;
  317.     h->locked = h->cacheflush = 0;
  318.     h->execute = NULL;
  319.     return h;
  320. }
  321.  
  322. static struct hash_entry *new_hash(CPTR addr)
  323. {
  324.     struct hash_entry *h = get_free_hash();
  325.     
  326.     h->addr = addr;
  327.  
  328.     /* Chain the new node */
  329.     h->prev = cpu_hash + ((addr >> 1) & HASH_MASK);
  330.     h->next = h->prev->next;
  331.     h->next->prev = h->prev->next = h;
  332.  
  333.     h->lru_next = &lru_first_hash;
  334.     h->lru_prev = lru_first_hash.lru_prev;
  335.     h->lru_prev->lru_next = h;
  336.     lru_first_hash.lru_prev = h;
  337.     
  338.     h->next_same_block = NULL;
  339.  
  340.     return h;
  341. }
  342.  
  343. static void lru_touch(struct hash_entry *h)
  344. {
  345.     if (0) {
  346.     h->lru_next->lru_prev = h->lru_prev;
  347.     h->lru_prev->lru_next = h->lru_next;
  348.     
  349.     h->lru_next = &lru_first_hash;
  350.     h->lru_prev = lru_first_hash.lru_prev;
  351.     h->lru_prev->lru_next = h;
  352.     lru_first_hash.lru_prev = h;
  353.     }
  354. }
  355.  
  356. static struct hash_entry *find_hash(CPTR addr)
  357. {
  358.     struct hash_entry *h;
  359.     struct hash_entry *h1 = cpu_hash + ((addr >> 1) & HASH_MASK);
  360.  
  361.     if (h1->next->addr == addr)
  362.     return h1->next;
  363.     
  364.     for (h = h1->next; h != h1; h = h->next) {
  365.     if (h->addr == addr) {
  366.         h->next->prev = h->prev; h->prev->next = h->next;
  367.         h->prev = h1;
  368.         h->next = h1->next;
  369.         h->next->prev = h->prev->next = h;
  370.         return h;
  371.     }
  372.     }
  373.     return NULL;
  374. }
  375.  
  376. static struct hash_entry *get_hash_for_func(CPTR addr)
  377. {
  378.     struct hash_entry *h = find_hash(addr);
  379.     if (h == NULL)
  380.     h = new_hash (addr);
  381.     else
  382.     lru_touch(h);
  383.     return h;
  384. }
  385.  
  386. static struct hash_entry *get_hash(CPTR addr)
  387. {
  388.     struct hash_entry *h = get_hash_for_func(addr);
  389.  
  390.     if (h->block == NULL) {
  391.     if (++h->ncalls == SCAN_MARK) {
  392.         m68k_scan_func(h);
  393.     }
  394.     } else
  395.     if (!h->block->untranslatable && h->block->nrefs++ == COMPILE_MARK) {
  396.         lru_touch_block(h->block);
  397.         if (m68k_compile_block(h->block)) {
  398.         h->block->untranslatable = 1;
  399.         } else
  400.         h->block->translated = 1;
  401.     }
  402.  
  403.     return h;
  404. }
  405.  
  406. void special_flush_hash(CPTR addr)
  407. {
  408.     struct hash_entry *h = get_hash_for_func(addr);
  409.     
  410.     h->cacheflush = 1;
  411. }
  412.  
  413. static __inline__ void m68k_setpc_hash(CPTR newpc)
  414. {
  415.     struct hash_entry *h = get_hash(newpc);
  416.     
  417.     if (h->cacheflush)
  418.     flush_icache();
  419.  
  420.     if (h->execute != NULL) {
  421.     if ((h->addr & 0xF80000) == 0xF80000 || check_block(h->block)) {
  422.         compiled_hits++;
  423.         if (i_want_to_die && (call_only_me == 0 || call_only_me == newpc)) {
  424.         exec_me = h->execute;
  425.         nr_bbs_to_run = nr_bbs_start;
  426.         regs.spcflags |= SPCFLAG_EXEC;
  427.         }
  428.     } else 
  429.         flush_icache();
  430.     }
  431.     regs.pc = newpc;
  432.     regs.pc_p = regs.pc_oldp = get_real_address(newpc);
  433. }
  434.  
  435. static __inline__ void m68k_setpc_nohash(CPTR newpc)
  436. {
  437. #if 0
  438.     /* This is probably not too good for efficiency... FIXME */
  439.     struct hash_entry *h = find_hash(newpc);
  440.  
  441.     if (h != NULL && h->cacheflush)
  442.     flush_icache();
  443. #endif
  444.     regs.pc = newpc;
  445.     regs.pc_p = regs.pc_oldp = get_real_address(newpc);
  446. }
  447.  
  448. void m68k_setpc(CPTR newpc)
  449. {
  450.     m68k_setpc_hash(newpc);    
  451. }
  452.  
  453. void m68k_setpc_fast(CPTR newpc)
  454. {
  455.     m68k_setpc_nohash(newpc);    
  456. }
  457.  
  458. void m68k_setpc_rte(CPTR newpc)
  459. {
  460.     m68k_setpc_nohash(newpc);
  461. }
  462.  
  463. void m68k_setpc_bcc(CPTR newpc)
  464. {
  465.     m68k_setpc_hash(newpc);
  466. }
  467.  
  468. static void hash_init(void)
  469. {
  470.     int i;
  471.     struct hash_entry **hepp;
  472.     
  473.     for(i = 0; i < NUM_HASH; i++) {
  474.     cpu_hash[i].next = cpu_hash[i].prev = cpu_hash + i;
  475.     cpu_hash[i].lru_next = cpu_hash[i].lru_prev = NULL;
  476.     cpu_hash[i].block = NULL;
  477.     cpu_hash[i].locked = 0; cpu_hash[i].cacheflush = 0;
  478.     cpu_hash[i].addr = -1;
  479.     }
  480.     hepp = &freelist_hash;
  481.     for(i = 0; i < NUM_FUNCTIONS; i++) {
  482.     *hepp = hash_entries + i;
  483.     hash_entries[i].next_same_block = NULL;
  484.     hash_entries[i].addr = -1;
  485.     hepp = &hash_entries[i].next_same_block;
  486.     }
  487.     lru_first_hash.lru_next = lru_first_hash.lru_prev = &lru_first_hash;
  488.     lru_first_block.lru_next = lru_first_block.lru_prev = &lru_first_block;
  489.     
  490.     freelist_block = NULL;
  491. }
  492.  
  493. static void code_init(void)
  494. {
  495.     first_code_page = NULL;
  496.     zerofd = open("/dev/zero", O_RDWR);
  497.     zeroff = 0;
  498. }
  499.  
  500. void compiler_init(void)
  501. {
  502.     int i;
  503.     code_init();
  504.     hash_init();
  505. }
  506.  
  507. /* Help function for the scan routine */
  508. static __inline__ int cc_flagmask(const int cc)
  509. {
  510.     switch(cc){
  511.      case 0: return 0;                       /* T */
  512.      case 1: return 0;                       /* F */
  513.      case 2: return 5;                       /* HI */
  514.      case 3: return 5;                       /* LS */
  515.      case 4: return 1;                       /* CC */
  516.      case 5: return 1;                       /* CS */
  517.      case 6: return 4;                       /* NE */
  518.      case 7: return 4;                       /* EQ */
  519.      case 8: return 2;                       /* VC */
  520.      case 9: return 2;                       /* VS */
  521.      case 10:return 8;                       /* PL */
  522.      case 11:return 8;                       /* MI */
  523.      case 12:return 10;                      /* GE */
  524.      case 13:return 10;                      /* LT */
  525.      case 14:return 14;                      /* GT */
  526.      case 15:return 14;                      /* LE */
  527.     }
  528.     abort();
  529.     return 0;
  530. }
  531.  
  532. static __inline__ void translate_step_over_ea(UBYTE **pcpp, amodes m, 
  533.                           wordsizes size)
  534. {
  535.     switch (m) {
  536.      case Areg:
  537.      case Dreg:
  538.      case Aind:
  539.      case Aipi:
  540.      case Apdi:
  541.      case immi:
  542.     break;
  543.  
  544.      case imm:
  545.     if (size == sz_long)
  546.         goto is_long;
  547.     /* fall through */
  548.      case Ad16:
  549.      case PC16:
  550.      case imm0:
  551.      case imm1:
  552.      case absw:
  553.     (*pcpp)+=2;
  554.     break;
  555.      case Ad8r:
  556.      case PC8r:
  557.     {
  558.         UWORD extra = *(*pcpp)++;
  559.         extra <<= 8;
  560.         extra |= *(*pcpp)++;
  561.         /* @@@ handle 68020 stuff here */
  562.     }
  563.     break;
  564.      case absl:
  565.      case imm2:
  566.     is_long:
  567.     (*pcpp) += 4;
  568.     break;
  569.     }
  570. }
  571.  
  572. static struct instr *translate_getnextinsn(UBYTE **pcpp)
  573. {
  574.     UWORD opcode;
  575.     struct instr *dp;
  576.     
  577.     opcode = *(*pcpp)++ << 8;
  578.     opcode |= *(*pcpp)++;
  579.     
  580.     if (cpufunctbl[opcode] == op_illg) {
  581.     opcode = 0x4AFC;
  582.     }
  583.     dp = table68k + opcode;
  584.     if (dp->suse) {
  585.     translate_step_over_ea(pcpp, dp->smode, dp->size);
  586.     }
  587.     if (dp->duse) {
  588.     translate_step_over_ea(pcpp, dp->dmode, dp->size);
  589.     }
  590.     return dp;
  591. }
  592.  
  593. #define CB_STACKSIZE 200
  594. #define BB_STACKSIZE 200
  595.  
  596. static ULONG condbranch_stack[CB_STACKSIZE];
  597. static int condbranch_src_stack[CB_STACKSIZE];
  598.  
  599. struct bb_info {
  600.     struct hash_entry *h;
  601.     CPTR stopaddr;
  602.     int can_compile_last;
  603.     struct bb_info *bb_next1, *bb_next2;
  604.     int flags_live_at_end;
  605.     int flags_live_at_start;
  606.     int first_iip, last_iip;
  607. } bb_stack[BB_STACKSIZE];
  608.  
  609. static int top_bb;
  610.  
  611. static CPTR bcc_target_stack[BB_STACKSIZE];
  612.  
  613. static int new_bcc_target(CPTR addr)
  614. {
  615.     int i;
  616.     
  617.     for (i = 0; i < top_bb; i++)
  618.     if (bcc_target_stack[i] == addr)
  619.         return 1;
  620.  
  621.     if (top_bb == BB_STACKSIZE)
  622.     return 0;
  623.     bcc_target_stack[top_bb++] = addr;
  624.     return 1;
  625. }
  626.  
  627. static int bcc_compfn(const void *a, const void *b)
  628. {
  629.     CPTR *a1 = (CPTR *)a, *b1 = (CPTR *)b;
  630.     
  631.     if (*a1 == *b1)
  632.     printf("BUG!!\n");
  633.     
  634.     if (*a1 < *b1)
  635.     return 1;
  636.     return -1;
  637. }
  638.  
  639. static int bb_compfn(const void *a, const void *b)
  640. {
  641.     struct bb_info *a1 = (struct bb_info *)a, *b1 = (struct bb_info *)b;
  642.     
  643.     if (a1->h->addr == b1->h->addr)
  644.     printf("BUG!!\n");
  645.     
  646.     if (a1->h->addr < b1->h->addr)
  647.     return -1;
  648.     return 1;
  649. }
  650.  
  651. static int find_basic_blocks(struct hash_entry *h)
  652. {
  653.     int current_bb = 0;
  654.  
  655.     top_bb = 0;
  656.     bcc_target_stack[0] = h->addr;
  657.     new_bcc_target(h->addr);
  658.  
  659.     while (top_bb > current_bb) {
  660.     CPTR addr = bcc_target_stack[current_bb];
  661.     int ninsns = 0;
  662.     UBYTE *realpc = get_real_address(addr);
  663.     UBYTE *rpc_start = realpc;
  664.     
  665.     for(;;) {
  666.         CPTR thisinsn_addr = (realpc - rpc_start) + addr;
  667.         UBYTE *rpc_save = realpc;
  668.         struct instr *dp = translate_getnextinsn(&realpc);
  669.         CPTR nextinsn_addr = (realpc - rpc_start) + addr;
  670.  
  671.         if (dp->mnemo == i_RTS || dp->mnemo == i_RTE 
  672.         || dp->mnemo == i_RTR || dp->mnemo == i_RTD
  673.         || dp->mnemo == i_JMP || dp->mnemo == i_ILLG) 
  674.         {
  675.         break;
  676.         }
  677.         
  678.         if (dp->mnemo == i_BSR || dp->mnemo == i_JSR) {
  679.         if (!new_bcc_target(nextinsn_addr))
  680.             return 0;
  681.         break;
  682.         }
  683.  
  684.         if (dp->mnemo == i_DBcc) {
  685.         CPTR newaddr = thisinsn_addr + 2 + (WORD)((*(rpc_save+2) << 8) | *(rpc_save+3));
  686.         if (!new_bcc_target(nextinsn_addr))
  687.             return 0;
  688.         if (!new_bcc_target(newaddr))
  689.             return 0;
  690.         break;
  691.         }
  692.         
  693.         if (dp->mnemo == i_Bcc) {
  694.         CPTR newaddr;
  695.         if (dp->smode == imm1)
  696.             newaddr = thisinsn_addr + 2 + (WORD)((*(rpc_save+2) << 8) | *(rpc_save+3));
  697.         else
  698.             newaddr = thisinsn_addr + 2 + (BYTE)dp->sreg;
  699.         
  700.         if (dp->cc != 0)
  701.             if (!new_bcc_target(nextinsn_addr))
  702.             return 0;
  703.         if (!new_bcc_target(newaddr))
  704.             return 0;
  705.         break;
  706.         }
  707.     }
  708.     current_bb++;
  709.     }
  710.  
  711.     qsort(bcc_target_stack, top_bb, sizeof (CPTR), bcc_compfn);
  712.  
  713.     return 1;
  714. }
  715.  
  716. static int m68k_scan_func(struct hash_entry *h)
  717. {
  718.     int i;
  719.     struct hash_block *found_block;
  720.     struct hash_entry **hepp;
  721.     
  722.     if (!find_basic_blocks(h))
  723.     return 0;
  724.  
  725.     found_block = NULL;
  726.     
  727.     for (i = 0; i < top_bb; i++) {
  728.     struct hash_entry *h = get_hash_for_func(bcc_target_stack[i]);
  729.     bb_stack[i].h = h;
  730.     /* if (h->block != NULL && h->block != found_block) {
  731.         if (found_block == NULL) {
  732.         if (h->block->cpage != NULL)
  733.             fprintf(stderr, "Found compiled code\n");
  734.         else
  735.             found_block = h->block;
  736.         } else {
  737.         fprintf(stderr, "Multiple blocks found.\n");
  738.         if (h->block->cpage == NULL)
  739.             forget_block(h->block);
  740.         else if (found_block->cpage == NULL) {
  741.             forget_block(found_block);
  742.             found_block = h->block;
  743.         } else
  744.             fprintf(stderr, "Bad case.\n");
  745.         }
  746.     }*/
  747.     }
  748.     if (found_block == NULL) {
  749.     found_block = new_block();
  750.  
  751.     found_block->lru_next = &lru_first_block;
  752.     found_block->lru_prev = lru_first_block.lru_prev;
  753.     found_block->lru_prev->lru_next = found_block;
  754.     lru_first_block.lru_prev = found_block;
  755.     }
  756.  
  757.     hepp = &found_block->he_first;
  758.     found_block->he_first = NULL;
  759.     for (i = 0; i < top_bb; i++) {
  760.     struct bb_info *bb = bb_stack + i;
  761.  
  762.     if (bb->h->block == NULL) {
  763.         bb->h->block = found_block;
  764.         *hepp = bb->h;
  765.         hepp = &bb->h->next_same_block;
  766.     }
  767.     }
  768.     *hepp = found_block->he_first;
  769.     return 1;
  770. }
  771.  
  772. struct ea_reg_info {
  773.     enum { eat_reg, eat_imem, eat_amem, eat_const } ea_type;
  774.     int regs_set:16;
  775.     int regs_used:16;
  776.     int nr_scratch;
  777.     ULONG temp1, temp2;
  778. };
  779.  
  780. #define MAX_TRANSLATE 2048
  781. struct insn_info_struct {
  782.     CPTR address;
  783.     struct instr *dp;
  784.     int flags_set;
  785.     int flags_used;
  786.     int flags_live_at_end;
  787.     int jump_target;
  788.     int jumps_to;
  789.     char *compiled_jumpaddr; /* Address to use for jumps to this insn */
  790.     char *compiled_fillin;   /* Address where to put offset if this is a Bcc */
  791.     int regs_set:16;
  792.     int regs_used:16;
  793.     int stop_translation:1;
  794.     int sync_cache:1;
  795.     int sync_flags:1;
  796.     int ccuser_follows:1;
  797. } insn_info [MAX_TRANSLATE];
  798.  
  799. #define EA_LOAD 1
  800. #define EA_STORE 2
  801. #define EA_IN_REG 4 /* Not quite sure yet what this flag will mean... :) */
  802. #if 0
  803. static void analyze_ea_for_insn(amodes mode, int reg, wordsizes size,
  804.                 struct ea_reg_info *eai,
  805.                 UBYTE **pcpp, CPTR pca,
  806.                 int ea_purpose)
  807. {
  808.     UBYTE *p = *pcpp;
  809.  
  810.     switch(mode) {
  811.      case Dreg:
  812.     eai->ea_type = eat_reg;
  813.     if (size != sz_long && (ea_purpose & EA_STORE))
  814.         ea_purpose |= EA_LOAD;
  815.     if (ea_purpose & EA_LOAD)
  816.         eai->regs_used |= 1 << reg;
  817.     if (ea_purpose & EA_STORE)
  818.         eai->regs_set |= 1 << reg;
  819.     break;
  820.     
  821.      case Areg:
  822.     eai->ea_type = eat_reg;
  823.     if (size != sz_long && (ea_purpose & EA_STORE))
  824.         printf("Areg != long\n");
  825.     if (ea_purpose & EA_LOAD)
  826.         eai->regs_used |= 1 << (8+reg);
  827.     if (ea_purpose & EA_STORE)
  828.         eai->regs_set |= 1 << (8+reg);
  829.     break;
  830.     
  831.      case Ad16:
  832.      case Aind:
  833.      case Apdi:
  834.      case Aipi:
  835.     eai->ea_type = eat_imem;
  836.     eai->regs_used |= 1 << (8+reg);
  837.     break;
  838.  
  839.      case Ad8r:
  840.     eai->ea_type = eat_imem;
  841.     pii->regs_used |= 1 << (8+reg);
  842.  
  843.     eai->temp = (UWORD)((*p << 8) | *(p+1));
  844.     r = (eai->temp & 0x7000) >> 12;
  845.     (*pcpp) += 2; p += 2;    
  846.     
  847.     if (eai->temp1 & 0x8000)
  848.         pii->regs_used |= 1 << (8+r);
  849.     else
  850.         pii->regs_used |= 1 << r;
  851.     break;
  852.  
  853.      case PC8r:
  854.     eai->ea_type = eat_imem;
  855.     eai->temp1 = (UWORD)((*p << 8) | *(p+1));
  856.     eai->temp2 = pca + (BYTE)eai->temp1;
  857.     (*pcpp) += 2; p += 2;
  858.     r = (eai->temp1 & 0x7000) >> 12;
  859.  
  860.     if (eai->temp1 & 0x8000)
  861.         pii->regs_used |= 1 << (8+r);
  862.     else
  863.         pii->regs_used |= 1 << r;
  864.     break;
  865.     
  866.      case PC16:    
  867.     eai->ea_type = eat_amem;
  868.     eai->temp1 = pca + (WORD)((*p << 8) | *(p+1));
  869.     (*pcpp) += 2;
  870.     break;
  871.     
  872.      case absw:
  873.     eai->ea_type = eat_amem;
  874.     eai->temp1 = (WORD)((*p << 8) | *(p+1));
  875.     (*pcpp) += 2;
  876.     break;
  877.  
  878.      case absl:
  879.     eai->ea_type = eat_amem;
  880.     eai->temp1 = (LONG)((*p << 24) | (*(p+1) << 16)
  881.                    | (*(p+2) << 8) | *(p+3));
  882.     (*pcpp) += 4;
  883.     break;
  884.  
  885.      case imm:
  886.     if (size == sz_long)
  887.         goto imm2_const;
  888.     if (size == sz_word)
  889.         goto imm1_const;
  890.     
  891.     /* fall through */
  892.      case imm0:
  893.     eai->ea_type = eat_imm;
  894.     eai->temp1 = (BYTE)*(p+1);
  895.     (*pcpp) += 2;
  896.     break;
  897.  
  898.      case imm1:
  899.     imm1_const:
  900.     eai->ea_type = eat_imm;
  901.     eai->temp1 = (WORD)((*p << 8) | *(p+1));
  902.     (*pcpp) += 2;
  903.     break;
  904.  
  905.      case imm2:
  906.     imm2_const:
  907.     eai->ea_type = eat_imm;
  908.     eai->temp1 = (LONG)((*p << 24) | (*(p+1) << 16) | (*(p+2) << 8) | *(p+3));
  909.     (*pcpp) += 4;
  910.     break;
  911.  
  912.      case immi:
  913.     eai->ea_type = eat_imm;
  914.     eai->temp1 = (BYTE)reg;
  915.     break;
  916.  
  917.      default:
  918.     break;
  919.     }
  920. }
  921. #endif
  922. static struct bb_info *find_bb(struct hash_entry *h)
  923. {
  924.     int i;
  925.     
  926.     for (i = 0; i < top_bb; i++)
  927.     if (bb_stack[i].h == h)
  928.         return bb_stack + i;
  929.     if (!quiet_compile)
  930.     fprintf(stderr, "BB not found!\n");
  931.     return NULL;
  932. }
  933.  
  934. static int m68k_scan_block(struct hash_block *hb, int *movem_count)
  935. {
  936.     struct hash_entry *h = hb->he_first;
  937.     int i, iip, last_iip;
  938.     
  939.     top_bb = 0;
  940.     
  941.     do {
  942.     struct bb_info *bb = bb_stack + top_bb;
  943.     bb->h = h;
  944.     bb->bb_next1 = NULL;
  945.     bb->bb_next2 = NULL;
  946.     h = h->next_same_block;
  947.     top_bb++;
  948.     } while (h != hb->he_first);
  949.     
  950.     qsort(bb_stack, top_bb, sizeof (struct bb_info), bb_compfn);
  951.  
  952.     *movem_count = 0;
  953.  
  954.     iip = 0;
  955.     for (i = 0; i < top_bb; i++) {
  956.     struct bb_info *bb = bb_stack + i;
  957.     UBYTE *realpc = get_real_address(bb->h->addr);
  958.     UBYTE *rpc_start = realpc;
  959.     CPTR stop_addr = 0;
  960.     int live_at_start = 31, may_clear_las = 31;
  961.     struct insn_info_struct *prev_ii = NULL;
  962.  
  963.     if (i < top_bb - 1)
  964.         stop_addr = (bb+1)->h->addr;
  965.     bb->first_iip = iip;
  966.  
  967.     for (;;) {
  968.         struct insn_info_struct *thisii = insn_info + iip;
  969.         CPTR thisinsn_addr = (realpc - rpc_start) + bb->h->addr;
  970.         UBYTE *rpc_save = realpc;
  971.         struct instr *dp = translate_getnextinsn(&realpc);
  972.         CPTR nextinsn_addr = (realpc - rpc_start) + bb->h->addr;
  973.         
  974.         int fset = dp->flagdead == -1 ? 31 : dp->flagdead;
  975.         int fuse = dp->flaglive == -1 ? 31 : dp->flaglive;
  976.         
  977.         if (thisinsn_addr == stop_addr) {
  978.         bb->bb_next1 = find_bb (find_hash (thisinsn_addr));
  979.         break;
  980.         }
  981.         
  982.         if (dp->mnemo == i_Scc || dp->mnemo == i_Bcc || dp->mnemo == i_DBcc) {
  983.         fset = 0, fuse = cc_flagmask(dp->cc);
  984.         if (prev_ii && dp->mnemo != i_Scc) /* Don't use Scc here: ea can cause an exit */
  985.             prev_ii->ccuser_follows = 1;
  986.         }
  987.  
  988.         may_clear_las &= ~fuse;
  989.         live_at_start &= ~(fset & may_clear_las);
  990.         
  991.         thisii->dp = dp;
  992.         thisii->address = thisinsn_addr;
  993.         thisii->stop_translation = 0;
  994.         thisii->ccuser_follows = 0;
  995. /*        thisii->have_reginfo = 0;*/
  996.         thisii->jump_target = 0;
  997.         thisii->sync_cache = thisii->sync_flags = 0;
  998.         thisii->flags_set = fset;
  999.         thisii->flags_used = fuse;
  1000.         thisii->regs_set = 0;
  1001.         thisii->regs_used = 0;
  1002.         iip++;
  1003.         if (iip == MAX_TRANSLATE)
  1004.         return 0;
  1005.  
  1006.         if (dp->mnemo == i_RTS || dp->mnemo == i_RTE 
  1007.         || dp->mnemo == i_RTR || dp->mnemo == i_RTD
  1008.         || dp->mnemo == i_JMP || dp->mnemo == i_ILLG
  1009.         || dp->mnemo == i_BSR || dp->mnemo == i_JSR)
  1010.         {
  1011.         thisii->flags_used = 31;
  1012.         thisii->regs_used = 65535;
  1013.         thisii->stop_translation = 1;
  1014.         break;
  1015.         }
  1016.         
  1017.         if (dp->mnemo == i_DBcc) {
  1018.         CPTR newaddr = thisinsn_addr + 2 + (WORD)((*(rpc_save+2) << 8) | *(rpc_save+3));
  1019.         bb->can_compile_last = 1;
  1020.         bb->bb_next1 = find_bb (find_hash (newaddr));
  1021.         if (bb->bb_next1 == NULL)
  1022.             thisii->stop_translation = 1;
  1023.         bb->bb_next2 = find_bb (find_hash (nextinsn_addr));
  1024.         if (bb->bb_next2 == NULL)
  1025.             thisii->stop_translation = 1;
  1026.         thisii->regs_used = 65535;
  1027.         break;
  1028.         }
  1029.         
  1030.         if (dp->mnemo == i_Bcc) {
  1031.         CPTR newaddr;
  1032.         if (dp->smode == imm1)
  1033.             newaddr = thisinsn_addr + 2 + (WORD)((*(rpc_save+2) << 8) | *(rpc_save+3));
  1034.         else
  1035.             newaddr = thisinsn_addr + 2 + (BYTE)dp->sreg;
  1036.         bb->can_compile_last = 1;
  1037.         bb->bb_next1 = find_bb(get_hash_for_func(newaddr));
  1038.         if (bb->bb_next1 == NULL)
  1039.             thisii->stop_translation = 1;
  1040.         if (dp->cc != 0) {
  1041.             bb->bb_next2 = find_bb(get_hash_for_func(nextinsn_addr));
  1042.             if (bb->bb_next2 == NULL)
  1043.             thisii->stop_translation = 1;
  1044.         }
  1045.         thisii->regs_used = 65535;
  1046.         break;
  1047.         }
  1048.  
  1049.         if (dp->mnemo == i_MVMLE || dp->mnemo == i_MVMEL) {
  1050.         UWORD regmask = (*(rpc_save + 2) << 8) | (*(rpc_save + 3));
  1051.         *movem_count += count_bits(regmask);
  1052.         if (dp->dmode == Apdi)
  1053.             regmask = bitswap(regmask);
  1054.         if (dp->mnemo == i_MVMLE)
  1055.             thisii->regs_used = regmask;
  1056.         else
  1057.             thisii->regs_set = regmask;
  1058.         }
  1059.  
  1060.         prev_ii = thisii;
  1061.     }
  1062.     bb->last_iip = iip - 1;
  1063.     bb->flags_live_at_start = live_at_start;
  1064.     }
  1065.     last_iip = iip;
  1066.  
  1067.     for (i = 0; i < top_bb; i++) {
  1068.     struct bb_info *bb = bb_stack + i;
  1069.     int mnemo;
  1070.     int current_live;
  1071.     struct instr *dp;
  1072.     
  1073.     iip = bb->last_iip;
  1074.     mnemo = insn_info[iip].dp->mnemo;
  1075.  
  1076.     /* Fix up branches */
  1077.     if (mnemo == i_DBcc || mnemo == i_Bcc) {
  1078.         if (bb->bb_next1 != NULL) {
  1079.         insn_info[bb->last_iip].jumps_to = bb->bb_next1->first_iip;
  1080.         insn_info[bb->bb_next1->first_iip].jump_target = 1;
  1081.         }
  1082.     }
  1083.     /* And take care of flag life information */
  1084.     dp = insn_info[iip].dp;
  1085.     if (insn_info[iip].stop_translation)
  1086.         current_live = 31;
  1087.     else if (dp->mnemo == i_DBcc || dp->mnemo == i_Bcc) {
  1088.         current_live = 0;
  1089.         if (bb->bb_next1 != NULL)
  1090.         current_live |= bb->bb_next1->flags_live_at_start;
  1091.         if (bb->bb_next2 != NULL)
  1092.         current_live |= bb->bb_next2->flags_live_at_start;
  1093.     } else {
  1094.         if (bb->bb_next1 == NULL && bb->bb_next2 == NULL)
  1095.         fprintf(stderr, "Can't happen\n");
  1096.         current_live = 0;
  1097.         if (bb->bb_next1 != NULL)
  1098.         current_live |= bb->bb_next1->flags_live_at_start;
  1099.         if (bb->bb_next2 != NULL)
  1100.         current_live |= bb->bb_next2->flags_live_at_start;
  1101.     }
  1102.  
  1103.     do {
  1104.         insn_info[iip].flags_live_at_end = current_live;
  1105.         current_live &= ~insn_info[iip].flags_set;
  1106.         current_live |= insn_info[iip].flags_used;
  1107.     } while (iip-- != bb->first_iip);
  1108.  
  1109.     if (bb->flags_live_at_start != current_live && !quiet_compile)
  1110.         fprintf(stderr, "Fascinating!\n");
  1111.     bb->flags_live_at_start = current_live;
  1112.     }
  1113.     return last_iip;
  1114. }
  1115.  
  1116. static char *compile_current_addr;
  1117. static char *compile_last_addr;
  1118.  
  1119. static __inline__ void assemble(UBYTE a)
  1120. {
  1121.     if (compile_current_addr < compile_last_addr) {
  1122.     *compile_current_addr++ = a;
  1123.     } else {
  1124.     compile_failure = 1;
  1125.     }
  1126. }
  1127.  
  1128. static __inline__ void assemble_ulong(ULONG a)
  1129. {
  1130.     assemble(a);
  1131.     assemble(a >> 8);
  1132.     assemble(a >> 16);
  1133.     assemble(a >> 24);
  1134. }
  1135.  
  1136. static __inline__ void assemble_uword(UWORD a)
  1137. {
  1138.     assemble(a);
  1139.     assemble(a >> 8);
  1140. }
  1141.  
  1142. static __inline__ void assemble_long(void *a)
  1143. {
  1144.     assemble_ulong((ULONG)a);
  1145. }
  1146.  
  1147. static __inline__ void compile_org(char *addr)
  1148. {
  1149.     compile_current_addr = addr;
  1150. }
  1151.  
  1152. static __inline__ char *compile_here(void)
  1153. {
  1154.     return compile_current_addr;
  1155. }
  1156.  
  1157. #define r_EAX 0
  1158. #define r_ECX 1
  1159. #define r_EDX 2
  1160. #define r_EBX 3
  1161. #define r_ESP 4
  1162. #define r_EBP 5
  1163. #define r_ESI 6
  1164. #define r_EDI 7
  1165.  
  1166. #define r_AH 0x84
  1167. #define r_CH 0x85
  1168. #define r_DH 0x86
  1169. #define r_BH 0x87
  1170.  
  1171. #define ALL_X86_REGS 255
  1172. #define ADDRESS_X86_REGS ((1 << r_EBP) | (1 << r_ESI) | (1 << r_EDI))
  1173. #define DATA_X86_REGS ((1 << r_EAX) | (1 << r_EDX) | (1 << r_EBX) | (1 << r_ECX))
  1174.  
  1175. #define BO_NORMAL 0
  1176. #define BO_SWAPPED_LONG 1
  1177. #define BO_SWAPPED_WORD 2
  1178.  
  1179. struct register_mapping {
  1180.     int dreg_map[8], areg_map[8]; /* 68000 register cache */
  1181.     int x86_const_offset[8];
  1182.     int x86_dirty[8];
  1183.     int x86_cache_reg[8]; /* Regs used for the 68000 register cache */
  1184.     int x86_cr_type[8]; /* Caching data or address register? */
  1185.     int x86_locked[8]; /* Regs used for some purpose */
  1186.     int x86_byteorder[8];
  1187.     int x86_verified[8];
  1188. };
  1189.  
  1190. /*
  1191.  * First, code to compile some primitive x86 instructions
  1192.  */
  1193.  
  1194. static void compile_lea_reg_with_offset(int dstreg, int srcreg, ULONG srcoffs)
  1195. {
  1196.     assemble(0x8D);
  1197.     if (srcreg == -2) {
  1198.     assemble(0x05 + 8*dstreg);
  1199.     assemble_ulong(srcoffs);
  1200.     } else if ((LONG)srcoffs >= -128 && (LONG)srcoffs <= 127) {
  1201.     assemble(0x40 + 8*dstreg + srcreg);
  1202.     assemble(srcoffs);
  1203.     } else {
  1204.     assemble(0x80 + 8*dstreg + srcreg);
  1205.     assemble_ulong(srcoffs);
  1206.     }
  1207. }
  1208.  
  1209. static void compile_move_reg_reg(int dstreg, int srcreg, wordsizes size)
  1210. {
  1211.     if (size == sz_byte
  1212.     && (((1 << dstreg) & DATA_X86_REGS) == 0
  1213.         || ((1 << srcreg) & DATA_X86_REGS) == 0))
  1214.     {
  1215.     fprintf(stderr, "Moving wrong register types!\n");
  1216.     }
  1217.     if (size == sz_word)
  1218.     assemble(0x66);
  1219.     if (size == sz_byte)
  1220.     assemble(0x88);
  1221.     else
  1222.     assemble(0x89);
  1223.     assemble(0xC0 + dstreg + 8*srcreg);
  1224. }
  1225.  
  1226. static void compile_move_between_reg_mem_regoffs(int dstreg, int srcreg,
  1227.                          ULONG srcoffs, wordsizes size,
  1228.                          int code)
  1229. {
  1230.     if (size == sz_byte && (dstreg & 0x80) != 0)
  1231.     dstreg &= ~0x80;
  1232.     else if ((size == sz_byte
  1233.           && ((1 << dstreg) & DATA_X86_REGS) == 0)
  1234.          || (size != sz_byte && (dstreg & 0x80) != 0))
  1235.     {
  1236.     fprintf(stderr, "Moving wrong register types!\n");
  1237.     }
  1238.     if (size == sz_word)
  1239.     assemble(0x66);
  1240.     if (size == sz_byte)
  1241.     assemble(code);
  1242.     else
  1243.     assemble(code + 1);
  1244.     
  1245.     if (srcreg == -2) {
  1246.     assemble(0x05 + 8*dstreg);
  1247.     assemble_ulong(srcoffs);
  1248.     } else if ((LONG)srcoffs >= -128 && (LONG)srcoffs <= 127) {
  1249.     assemble(0x40 + 8*dstreg + srcreg);
  1250.     assemble(srcoffs);
  1251.     } else {
  1252.     assemble(0x80 + 8*dstreg + srcreg);
  1253.     assemble_ulong(srcoffs);
  1254.     }
  1255. }
  1256.  
  1257. static void compile_move_reg_from_mem_regoffs(int dstreg, int srcreg, 
  1258.                           ULONG srcoffs, wordsizes size)
  1259. {
  1260.     compile_move_between_reg_mem_regoffs(dstreg, srcreg, srcoffs, size, 0x8A);
  1261. }
  1262.  
  1263. static void compile_move_reg_to_mem_regoffs(int dstreg, ULONG dstoffs, 
  1264.                         int srcreg, wordsizes size)
  1265. {
  1266.     compile_move_between_reg_mem_regoffs(srcreg, dstreg, dstoffs, size, 0x88);
  1267. }
  1268.  
  1269. static void compile_byteswap(int x86r, wordsizes size, int save_flags)
  1270. {
  1271.     switch(size) {
  1272.      case sz_word:
  1273.     if (save_flags)
  1274.         assemble(0x9C);
  1275.     assemble(0x66); /* rolw $8,x86r */
  1276.     assemble(0xC1);
  1277.     assemble(0xC0 + x86r);
  1278.     assemble(8);
  1279.     if (save_flags)
  1280.         assemble(0x9D);
  1281.     break;
  1282.      case sz_long:
  1283.     assemble(0x0F); /* bswapl x86r */
  1284.     assemble(0xC8+x86r);
  1285.     break;
  1286.      default:
  1287.     break;
  1288.     }
  1289. }
  1290.  
  1291. static void compile_force_byteorder(struct register_mapping *map, int x86r,
  1292.                     int desired_bo, int save_flags)
  1293. {
  1294.     if (x86r == -2 || map->x86_byteorder[x86r] == desired_bo)
  1295.     return;
  1296.     
  1297.     if (map->x86_byteorder[x86r] == BO_SWAPPED_LONG)
  1298.     compile_byteswap(x86r, sz_long, save_flags);
  1299.     else if (map->x86_byteorder[x86r] == BO_SWAPPED_WORD)
  1300.     compile_byteswap(x86r, sz_word, save_flags);
  1301.     
  1302.     if (desired_bo == BO_SWAPPED_LONG)
  1303.     compile_byteswap(x86r, sz_long, save_flags);
  1304.     else if (desired_bo == BO_SWAPPED_WORD)
  1305.     compile_byteswap(x86r, sz_word, save_flags);
  1306.     map->x86_byteorder[x86r] = desired_bo;
  1307. }
  1308.  
  1309. /* Add a constant offset to a x86 register. If it's in the cache, make sure
  1310.  * we update the const_offset value. The flags are unaffected by this */
  1311.  
  1312. static void compile_offset_reg(struct register_mapping *map, int x86r, 
  1313.                    ULONG offset)
  1314. {
  1315.     int cached_68k;
  1316.     
  1317.     if (offset == 0 || x86r == -1 || x86r == -2)
  1318.     return;
  1319.  
  1320.     compile_force_byteorder(map, x86r, BO_NORMAL, 1);
  1321.     cached_68k = map->x86_cache_reg[x86r];
  1322.     if (cached_68k != -1) {
  1323.     map->x86_const_offset[x86r] -= offset;
  1324.     map->x86_dirty[x86r] = 1;
  1325.     }
  1326.     compile_lea_reg_with_offset(x86r, x86r, offset);
  1327. }
  1328.  
  1329. static int get_unused_x86_register(struct register_mapping *map)
  1330. {
  1331.     int x86r;
  1332.     for (x86r = 0; x86r < 24; x86r++) {
  1333.     if (map->x86_cache_reg[x86r] != -1)
  1334.         continue;
  1335.     if (map->x86_locked[x86r] > 0)
  1336.         continue;
  1337.     
  1338.     map->x86_verified[x86r] = 0;
  1339.     map->x86_byteorder[x86r] = BO_NORMAL;
  1340.     return x86r;
  1341.     }
  1342.     return -1;
  1343. }
  1344.  
  1345. /*
  1346.  * sync_reg() may not touch the flags
  1347.  * If may_clobber is 1 and the reg had an offset, the reg will be offsetted
  1348.  * by this function
  1349.  */
  1350. static void sync_reg(struct register_mapping *map, int x86r, void *m68kr, 
  1351.              ULONG offset, int dirty, int may_clobber)
  1352. {
  1353.     compile_force_byteorder(map, x86r, BO_NORMAL, 1);
  1354.     if (offset != 0) {
  1355.     if (may_clobber) {
  1356.         compile_lea_reg_with_offset(x86r, x86r, offset);
  1357.         dirty = 1;
  1358.     } else {
  1359.         int tmpr = get_unused_x86_register(map);
  1360.         if (tmpr != -1) { 
  1361.         compile_lea_reg_with_offset(tmpr, x86r, offset);
  1362.         x86r = tmpr;
  1363.         dirty = 1;
  1364.         } else {
  1365.         compile_lea_reg_with_offset(x86r, x86r, offset);
  1366.         assemble(0x89);          /* movl x86r,m68kr */
  1367.         assemble(0x05 + (x86r << 3)); 
  1368.         assemble_long(m68kr);
  1369.         compile_lea_reg_with_offset(x86r, x86r, -offset);
  1370.         return;
  1371.         }
  1372.     }
  1373.     }
  1374.  
  1375.     if (dirty) {
  1376.     assemble(0x89);          /* movl x86r,m68kr */
  1377.     assemble(0x05 + (x86r << 3)); 
  1378.     assemble_long(m68kr);
  1379.     }
  1380. }
  1381.  
  1382. static void sync_reg_cache(struct register_mapping *map, int flush)
  1383. {
  1384.     int i;
  1385.  
  1386.     for (i = 0; i < 8; i++) {
  1387.     int cr68k = map->x86_cache_reg[i];
  1388.     if (cr68k != -1) {
  1389.         if (map->x86_cr_type[i] == 1) {
  1390.         sync_reg(map, i, regs.d + cr68k, map->x86_const_offset[i], map->x86_dirty[i], 1);
  1391.         if (flush)
  1392.             map->dreg_map[cr68k] = -1;
  1393.         } else {
  1394.         sync_reg(map, i, regs.a + cr68k, map->x86_const_offset[i], map->x86_dirty[i], 1);
  1395.         if (flush)
  1396.             map->areg_map[cr68k] = -1;
  1397.         }
  1398.         if (flush)
  1399.         map->x86_cache_reg[i] = -1;
  1400.         map->x86_const_offset[i] = 0;
  1401.     }
  1402.     }
  1403.     memset(map->x86_dirty, 0, sizeof map->x86_dirty);
  1404. }
  1405.  
  1406. static void remove_x86r_from_cache(struct register_mapping *map, int x86r, 
  1407.                    int may_clobber)
  1408. {
  1409.     int j;
  1410.     int reg_68k;
  1411.     
  1412.     if (x86r == -1)
  1413.     return;
  1414.  
  1415.     reg_68k = map->x86_cache_reg[x86r];
  1416.     
  1417.     if (reg_68k != -1) {
  1418.     if (map->x86_cr_type[x86r] == 1) {
  1419.         map->dreg_map[reg_68k] = -1;
  1420.         sync_reg(map, x86r, regs.d + reg_68k, map->x86_const_offset[x86r],
  1421.              map->x86_dirty[x86r], may_clobber);
  1422.     } else {
  1423.         map->areg_map[reg_68k] = -1;
  1424.         sync_reg(map, x86r, regs.a + reg_68k,  map->x86_const_offset[x86r],
  1425.              map->x86_dirty[x86r], may_clobber);
  1426.     }
  1427.     }
  1428.     map->x86_dirty[x86r] = 0;
  1429.     map->x86_cache_reg[x86r] = -1;
  1430.     map->x86_const_offset[x86r] = 0;
  1431.     map->x86_verified[x86r] = 0;
  1432.     map->x86_byteorder[x86r] = BO_NORMAL;
  1433. }
  1434.  
  1435. static int get_free_x86_register(struct register_mapping *map,
  1436.                  int preferred_mask)
  1437. {
  1438.     int cnt;
  1439.     for (cnt = 0; cnt < 24; cnt++) {
  1440.     int x86r = cnt & 7;
  1441.     /* In the first two passes, try to get one of the preferred regs */
  1442.     if (cnt < 16 && ((1 << x86r) & preferred_mask) == 0)
  1443.         continue;
  1444.     /* In the first pass, don't discard any registers from the cache */
  1445.     if (cnt < 8 && map->x86_cache_reg[x86r] != -1)
  1446.         continue;
  1447.     /* Never use locked registers */
  1448.     if (map->x86_locked[x86r] > 0)
  1449.         continue;
  1450.  
  1451.     remove_x86r_from_cache(map, x86r, 1);
  1452.     return x86r;
  1453.     }
  1454.     printf("Out of registers!\n");
  1455.     return -1;
  1456. }
  1457.  
  1458. static int get_typed_x86_register(struct register_mapping *map,
  1459.                   int preferred_mask)
  1460. {
  1461.     int cnt;
  1462.     for (cnt = 0; cnt < 16; cnt++) {
  1463.     int x86r = cnt & 7;
  1464.     /* Get one of the preferred regs */
  1465.     if (((1 << x86r) & preferred_mask) == 0)
  1466.         continue;
  1467.     /* In the first pass, don't discard any registers from the cache */
  1468.     if (cnt < 8 && map->x86_cache_reg[x86r] != -1)
  1469.         continue;
  1470.     /* Never use locked registers */
  1471.     if (map->x86_locked[x86r] > 0)
  1472.         continue;
  1473.  
  1474.     remove_x86r_from_cache(map, x86r, 1);
  1475.     return x86r;
  1476.     }
  1477.     printf("Out of type registers!\n");
  1478.     return -1;
  1479. }
  1480.  
  1481. static void compile_unlock_reg(struct register_mapping *map, int reg)
  1482. {
  1483.     if (reg >= 0) {
  1484.     map->x86_locked[reg]--;
  1485.     }
  1486. }
  1487.  
  1488. static int get_and_lock_68k_reg(struct register_mapping *map, int reg, int is_dreg,
  1489.                 int preferred, int no_offset)
  1490. {
  1491.     int x86r;
  1492.     int *regmap;
  1493.     ULONG *reghome;
  1494.     
  1495.     if (is_dreg)
  1496.     regmap = map->dreg_map, reghome = regs.d;
  1497.     else
  1498.     regmap = map->areg_map, reghome = regs.a;
  1499.     
  1500.     if (preferred == 0)
  1501.     preferred = ALL_X86_REGS;
  1502.     
  1503.     x86r = regmap[reg];
  1504.     if (x86r == -1) {
  1505.     x86r = get_free_x86_register(map, preferred);
  1506.     assemble(0x8B); assemble(0x05 + (x86r << 3)); /* movl regs.d[reg],x86r */
  1507.     assemble_long(reghome + reg);
  1508.     map->x86_cache_reg[x86r] = reg;
  1509.     map->x86_cr_type[x86r] = is_dreg;
  1510.     map->x86_const_offset[x86r] = 0;
  1511.     map->x86_dirty[x86r] = 0;
  1512.     map->x86_verified[x86r] = 0;
  1513.     map->x86_byteorder[x86r] = BO_NORMAL;
  1514.     regmap[reg] = x86r;
  1515.     } else if (map->x86_locked[x86r] > 0) {
  1516.     /* Register was in cache, and was locked. Need to make a copy */
  1517.     int newr = get_free_x86_register(map, preferred);
  1518.     int old_dirty = 0;
  1519.     int old_verified;
  1520.     int old_bo;
  1521.     
  1522.     if (map->x86_const_offset[x86r] == 0) {
  1523.         compile_move_reg_reg(newr, x86r, sz_long);
  1524.     } else {
  1525.         compile_force_byteorder(map, x86r, BO_NORMAL, 1);
  1526.         compile_lea_reg_with_offset(newr, x86r, map->x86_const_offset[x86r]);
  1527.         old_dirty = 1;
  1528.     }
  1529.     /* Remove old reg from cache... */
  1530.     map->x86_cache_reg[x86r] = -1;
  1531.     map->x86_cr_type[x86r] = is_dreg;
  1532.     map->x86_const_offset[x86r] = 0;
  1533.     old_dirty |= map->x86_dirty[x86r];
  1534.     old_verified = map->x86_verified[x86r];
  1535.     old_bo = map->x86_byteorder[x86r];
  1536.     map->x86_verified[x86r] = 0;
  1537.     map->x86_dirty[x86r] = 0;
  1538.     x86r = newr;
  1539.     /* ... and make the new one the cache register */
  1540.     map->x86_cache_reg[x86r] = reg;
  1541.     map->x86_cr_type[x86r] = is_dreg;
  1542.     map->x86_const_offset[x86r] = 0;
  1543.     map->x86_dirty[x86r] = old_dirty;
  1544.     map->x86_verified[x86r] = old_verified;
  1545.     map->x86_byteorder[x86r] = old_bo;
  1546.     regmap[reg] = x86r;
  1547.     }
  1548.     map->x86_locked[x86r]++;
  1549.     if (no_offset && map->x86_const_offset[x86r] != 0) {
  1550.     compile_force_byteorder(map, x86r, BO_NORMAL, 1);
  1551.     compile_lea_reg_with_offset(x86r, x86r, map->x86_const_offset[x86r]);
  1552.     map->x86_const_offset[x86r] = 0;
  1553.     map->x86_dirty[x86r] = 1;
  1554.     }
  1555.     return x86r;
  1556. }
  1557.  
  1558. /*
  1559.  * Move a constant to a register. Don't anything if we already have a
  1560.  * register, even if it is offset by a constant
  1561.  */
  1562.  
  1563. static int compile_force_const_reg(struct register_mapping *map, int x86r,
  1564.                    ULONG *offs, int desired)
  1565. {
  1566.     int newr = x86r;
  1567.  
  1568.     if (newr == -2) {
  1569.     if (desired == 0)
  1570.         newr = get_free_x86_register(map, ALL_X86_REGS);
  1571.     else
  1572.         newr = get_typed_x86_register(map, desired);
  1573.  
  1574.     assemble(0xB8 + newr);
  1575.     assemble_ulong(*offs);
  1576.     *offs = 0;
  1577.     }
  1578.     map->x86_locked[newr]++;
  1579.     return newr;
  1580. }
  1581.  
  1582. static int compile_extend_long(struct register_mapping *map, int x86r,
  1583.                    ULONG *srcoffs, wordsizes size)
  1584. {
  1585.     compile_force_byteorder(map, x86r, BO_NORMAL, 1);
  1586.     if (size != sz_long) {
  1587.     if (x86r == -2) {
  1588.         ULONG offs = *srcoffs;
  1589.         if (size == sz_byte)
  1590.         offs = (LONG)(BYTE)offs;
  1591.         else if (size == sz_word)
  1592.         offs = (LONG)(WORD)offs;
  1593.         *srcoffs = offs;
  1594.         return x86r;
  1595.     } else if (*srcoffs != 0) {
  1596.         int newr = get_free_x86_register(map, ALL_X86_REGS);
  1597.         compile_lea_reg_with_offset(newr, x86r, *srcoffs);
  1598.         *srcoffs = 0;
  1599.         x86r = newr;
  1600.     } else if (map->x86_locked[x86r] != 0) {
  1601.         int newr = get_free_x86_register(map, ALL_X86_REGS);
  1602.         assemble(0x0F);
  1603.         if (size == sz_byte) {
  1604.         assemble(0xBE);
  1605.         } else {
  1606.         assemble(0xBF);
  1607.         }
  1608.         assemble(0xC0 + newr*8 + x86r);
  1609.         x86r = newr;
  1610.         goto extended;
  1611.     }
  1612.     
  1613.     if (x86r == r_EAX && size == sz_word) {
  1614.         assemble(0x98); /* cwtl */
  1615.     } else {
  1616.         assemble(0x0F);
  1617.         if (size == sz_byte) {
  1618.         assemble(0xBE);
  1619.         } else {
  1620.         assemble(0xBF);
  1621.         }
  1622.         assemble(0xC0 + x86r*9);
  1623.     }
  1624.     }
  1625.     extended:
  1626.     if (x86r >= 0)
  1627.     map->x86_locked[x86r]++;
  1628.     return x86r;
  1629. }
  1630.  
  1631. /*
  1632.  * Either move a constant into a register, or get rid of a constant offset
  1633.  * for a register
  1634.  */
  1635.  
  1636. static int compile_move_const_reg(struct register_mapping *map, int x86r,
  1637.                   ULONG *offs, int desired)
  1638. {
  1639.     int newr = x86r;
  1640.     if (newr == -2) {
  1641.     if (desired == 0)
  1642.         newr = get_free_x86_register(map, ALL_X86_REGS);
  1643.     else
  1644.         newr = get_typed_x86_register(map, desired);
  1645.     assemble(0xB8 + newr);
  1646.     assemble_ulong(*offs);
  1647.     } else {
  1648.     compile_offset_reg(map, x86r, *offs);
  1649.     }
  1650.     *offs = 0;
  1651.     map->x86_locked[newr]++;
  1652.     return newr;
  1653. }
  1654.  
  1655. static int compile_move_to_modereg(struct register_mapping *map, int x86r, 
  1656.                    wordsizes size)
  1657. {
  1658.     int newr = x86r;
  1659.     
  1660.     if (size == sz_byte && ((1 << x86r) & DATA_X86_REGS) == 0) {
  1661.     newr = get_typed_x86_register(map, DATA_X86_REGS);
  1662.     compile_force_byteorder(map, x86r, BO_NORMAL, 1);
  1663.     if (((1 << newr) & DATA_X86_REGS) == 0)
  1664.         printf("Can't get data register for byte value\n");
  1665.     assemble(0x89);
  1666.     assemble(0xC0 + newr*8 + x86r);
  1667.     }
  1668.     map->x86_locked[newr]++;
  1669.     return newr;
  1670. }
  1671.  
  1672. /*
  1673.  * This structure holds information about predec/postinc addressing modes.
  1674.  */
  1675.  
  1676. struct pid_undo {
  1677.     int used;
  1678.     int x86r[2];
  1679.     int m68kr[2];
  1680.     int dirty[2];
  1681.     ULONG offs[2];
  1682. };
  1683.  
  1684. static void add_undo(struct pid_undo *pud, int x86r, int m68kr, ULONG offs,
  1685.              int dirty)
  1686. {
  1687.     int i;
  1688.     for (i = 0; i < pud->used; i++)
  1689.     if (pud->m68kr[i] == m68kr)
  1690.         return;
  1691.     pud->m68kr[i] = m68kr;
  1692.     pud->x86r[i] = x86r;
  1693.     pud->offs[i] = offs;
  1694.     pud->dirty[i] = dirty;
  1695.     pud->used++;
  1696. }
  1697.  
  1698. struct ea_info {
  1699.     int reg;
  1700.     amodes mode;
  1701.     wordsizes size;
  1702.     int regs_locked;    /* The regs locked for this ea by compile_prepareea() */
  1703.     int locked_regs[3];
  1704.     int address_reg;    /* The x86 reg holding the address, or -1 if ea doesn't refer to memory
  1705.              * -2 if it refers to memory, but only with a constant address */
  1706.     ULONG addr_const_off; /* Constant offset to the address */
  1707.     int flags;            /* Extra info. Contains the dp field of d8r modes */
  1708.     int purpose;
  1709.     int data_reg;         /* The x86 reg that holds the data. -1 if data is not present yet. 
  1710.                * -2 if data is constant */
  1711.     ULONG data_const_off;
  1712. };
  1713.  
  1714. static void init_eainfo(struct ea_info *eai)
  1715. {
  1716.     eai->regs_locked = 0;
  1717.     eai->address_reg = -1;
  1718.     eai->addr_const_off = 0;
  1719.     eai->data_reg = -1;
  1720.     eai->data_const_off = 0;
  1721. }
  1722.  
  1723. /*
  1724.  * Load all the registers absolutely needed to calculate and verify thea
  1725.  * address. Load other registers if convenient.
  1726.  * This contains a fair amount of magic to get the register cache working right.
  1727.  */
  1728.  
  1729. static void compile_prepareea(struct register_mapping *map, amodes mode,
  1730.                   int reg, wordsizes size, UBYTE **pcpp, CPTR pca,
  1731.                   struct ea_info *eai, int ea_purpose,
  1732.                   struct pid_undo *pud, int pidmult)
  1733. {
  1734.     int pdival = size == sz_byte && reg != 7 ? 1 : size == sz_long ? 4 : 2;
  1735.     UBYTE *p = *pcpp;
  1736.     UWORD dp;
  1737.     int r;
  1738.     int x86r, tmpr;
  1739.  
  1740.     pdival *= pidmult;
  1741.     
  1742.     init_eainfo(eai);
  1743.     eai->mode = mode;
  1744.     eai->size = size;
  1745.     eai->reg = reg;
  1746.     
  1747.     switch(mode){
  1748.      case Dreg:
  1749.     if (size != sz_long && (ea_purpose & EA_STORE))
  1750.         ea_purpose |= EA_LOAD;
  1751.     /* Is the register in the cache, or do we need it there? If so, lock it.
  1752.      * This will make sure we are the only ones who have it locked, so we
  1753.      * can mess with it without expecting surprises. 
  1754.      * Get it without a constant offset. */
  1755.     x86r = map->dreg_map[reg];
  1756.     if (x86r != -1 || (ea_purpose & EA_LOAD)) {
  1757.         eai->regs_locked = 1;
  1758.         x86r = eai->locked_regs[0] = get_and_lock_68k_reg(map, reg, 1, 0, 1);
  1759.     }
  1760.     /* And if we need to manipulate it with byte sizes, we ought to get it
  1761.      * into an appropriate register */
  1762.     if (size == sz_byte && x86r != -1 && (ea_purpose & (EA_LOAD|EA_STORE))
  1763.         && ((1 << x86r) & DATA_X86_REGS) == 0) 
  1764.     {
  1765.         int newr = get_typed_x86_register(map, DATA_X86_REGS);
  1766.         compile_force_byteorder(map, x86r, BO_NORMAL, 0);
  1767.         compile_move_reg_reg(newr, x86r, sz_long);
  1768.         map->x86_locked[newr]++;
  1769.         compile_unlock_reg(map, x86r);
  1770.         eai->locked_regs[0] = newr;
  1771.         
  1772.         /* We need to update the register cache, otherwise storeea
  1773.          * will mark the new one dirty, but that is never checked. */
  1774.         map->x86_const_offset[newr] = map->x86_const_offset[x86r];
  1775.         map->x86_dirty[newr] = map->x86_dirty[x86r];
  1776.         map->x86_cache_reg[x86r] = -1;
  1777.         map->x86_cache_reg[newr] = reg;
  1778.         map->x86_cr_type[newr] = 1;
  1779.         map->dreg_map[reg] = newr;
  1780.     }
  1781.     if (eai->regs_locked == 1) {
  1782.         eai->data_reg = eai->locked_regs[0];
  1783.         eai->data_const_off = map->x86_const_offset[eai->data_reg];
  1784.     }
  1785.     break;
  1786.     
  1787.      case Areg:
  1788.     if (size != sz_long && (ea_purpose & EA_STORE))
  1789.         printf("Areg != long\n");
  1790.     x86r = map->areg_map[reg];
  1791.     if (x86r != -1 || (ea_purpose & EA_LOAD)) {
  1792.         eai->regs_locked = 1;
  1793.         x86r = eai->locked_regs[0] = get_and_lock_68k_reg(map, reg, 0, 0, 1);
  1794.     }
  1795.     /* And if we need to get the byte part, we ought to get it
  1796.      * into an appropriate register */
  1797.     if (size == sz_byte && x86r != -1 && (ea_purpose & EA_LOAD)
  1798.         && ((1 << x86r) & DATA_X86_REGS) == 0)
  1799.     {
  1800.         int newr = get_typed_x86_register(map, DATA_X86_REGS);
  1801.         compile_force_byteorder(map, x86r, BO_NORMAL, 0);
  1802.         compile_move_reg_reg(newr, x86r, sz_long);
  1803.         map->x86_locked[newr]++;
  1804.         compile_unlock_reg(map, x86r);
  1805.         eai->locked_regs[0] = newr;
  1806.     }
  1807.     if (eai->regs_locked == 1) {
  1808.         eai->data_reg = eai->locked_regs[0];
  1809.         eai->data_const_off = map->x86_const_offset[eai->data_reg];
  1810.     }
  1811.     break;
  1812.     
  1813.      case Ad16:
  1814.     eai->addr_const_off = (WORD)((*p << 8) | *(p+1));
  1815.     (*pcpp) += 2; p += 2;
  1816.     x86r = eai->locked_regs[0] = eai->address_reg = get_and_lock_68k_reg(map, reg, 0, ADDRESS_X86_REGS, 0);
  1817.     compile_force_byteorder(map, x86r, BO_NORMAL, 0);
  1818.     eai->addr_const_off += map->x86_const_offset[x86r];
  1819.     eai->regs_locked = 1;
  1820.     break;
  1821.  
  1822.      case Aind:
  1823.     x86r = eai->locked_regs[0] = eai->address_reg = get_and_lock_68k_reg(map, reg, 0, ADDRESS_X86_REGS, 0);
  1824.     compile_force_byteorder(map, x86r, BO_NORMAL, 0);
  1825.     eai->addr_const_off = map->x86_const_offset[x86r];
  1826.     eai->regs_locked = 1;
  1827.     break;
  1828.     
  1829.      case Apdi:
  1830.     x86r = eai->locked_regs[0] = eai->address_reg = get_and_lock_68k_reg(map, reg, 0, ADDRESS_X86_REGS, 0);
  1831.     compile_force_byteorder(map, x86r, BO_NORMAL, 0);
  1832.     /* 
  1833.      * Add this reg with its current offset to the undo buffer.
  1834.      * Since we have locked it, we are certain that it will not be
  1835.      * modified at least before generate_possible_exits() has done its
  1836.      * job.
  1837.      */
  1838.     add_undo(pud, x86r, reg, map->x86_const_offset[x86r], map->x86_dirty[x86r]);
  1839.     map->x86_const_offset[x86r] -= pdival;
  1840.     eai->addr_const_off = map->x86_const_offset[x86r];
  1841.     eai->regs_locked = 1;
  1842.     break;
  1843.     
  1844.      case Aipi:
  1845.     x86r = eai->locked_regs[0] = eai->address_reg = get_and_lock_68k_reg(map, reg, 0, ADDRESS_X86_REGS, 0);
  1846.     compile_force_byteorder(map, x86r, BO_NORMAL, 0);
  1847.     add_undo(pud, x86r, reg, map->x86_const_offset[x86r], map->x86_dirty[x86r]);
  1848.     eai->addr_const_off = map->x86_const_offset[x86r];
  1849.     map->x86_const_offset[x86r] += pdival;
  1850.     eai->regs_locked = 1;
  1851.     break;
  1852.  
  1853.      case Ad8r:
  1854.     dp = (WORD)((*p << 8) | *(p+1));
  1855.     r = (dp & 0x7000) >> 12;
  1856.     (*pcpp) += 2; p += 2;    
  1857.     
  1858.     tmpr = get_and_lock_68k_reg(map, reg, 0, ADDRESS_X86_REGS, 0);
  1859.     x86r = get_and_lock_68k_reg(map, r, dp & 0x8000 ? 0 : 1, 0, 1);
  1860.     compile_force_byteorder(map, x86r, BO_NORMAL, 0);
  1861.     compile_force_byteorder(map, tmpr, BO_NORMAL, 0);
  1862.     eai->locked_regs[0] = eai->address_reg = get_free_x86_register(map, ADDRESS_X86_REGS);
  1863.     map->x86_locked[eai->address_reg]++;
  1864.     
  1865.     eai->addr_const_off = map->x86_const_offset[tmpr] + (BYTE)dp;
  1866.     r = (dp & 0x7000) >> 12;
  1867.  
  1868.     if (dp & 0x800) {
  1869.         if ((LONG)eai->addr_const_off >= -128 && (LONG)eai->addr_const_off <= 127) {
  1870.         assemble(0x8D); 
  1871.         assemble(0x44 + eai->address_reg*8); /* leal disp8(dispreg,basereg),addrreg */
  1872.         assemble(x86r*8 + tmpr);
  1873.         assemble(eai->addr_const_off);
  1874.         } else {
  1875.         assemble(0x8D);
  1876.         assemble(0x84 + eai->address_reg*8); /* leal disp32(dispreg,basereg),addrreg */
  1877.         assemble(x86r*8 + tmpr);
  1878.         assemble_ulong(eai->addr_const_off);
  1879.         }
  1880.         eai->addr_const_off = 0;
  1881.     } else {
  1882.         assemble(0x0F); assemble(0xBF);
  1883.         assemble(0xC0 + x86r + eai->address_reg*8); /* movswl dispreg,addrreg */
  1884.         assemble(0x03); assemble(0xC0 + tmpr + eai->address_reg*8); /* addl basereg,addrreg */
  1885.     }
  1886.     compile_unlock_reg(map, x86r);
  1887.     compile_unlock_reg(map, tmpr);
  1888.     eai->regs_locked = 1;
  1889.     break;
  1890.  
  1891.      case PC8r:
  1892.     dp = (WORD)((*p << 8) | *(p+1));
  1893.     (*pcpp) += 2; p += 2;
  1894.     r = (dp & 0x7000) >> 12;
  1895.     eai->addr_const_off = pca + (BYTE)dp;
  1896.     if (dp & 0x800) {
  1897.         eai->locked_regs[0] = eai->address_reg = get_and_lock_68k_reg(map, r, dp & 0x8000 ? 0 : 1, 0, 1);
  1898.     } else {
  1899.         eai->regs_locked = 2;
  1900.         tmpr = get_and_lock_68k_reg(map, r, dp & 0x8000 ? 0 : 1, 0, 1);
  1901.         compile_force_byteorder(map, tmpr, BO_NORMAL, 0);
  1902.         eai->locked_regs[0] = eai->address_reg = get_free_x86_register(map, ADDRESS_X86_REGS);
  1903.         map->x86_locked[eai->address_reg]++;
  1904.  
  1905.         assemble(0x0F); assemble(0xBF);
  1906.         assemble(0xC0 + tmpr + eai->address_reg*8); /* movswl dispreg,addrreg */
  1907.         compile_unlock_reg(map, tmpr);
  1908.     }
  1909.     eai->regs_locked = 1;
  1910.     break;
  1911.     
  1912.      case PC16:
  1913.     eai->addr_const_off = pca + (WORD)((*p << 8) | *(p+1));
  1914.     eai->address_reg = -2;
  1915.     (*pcpp) += 2; p += 2;
  1916.     break;
  1917.     
  1918.      case absw:
  1919.     eai->addr_const_off = (WORD)((*p << 8) | *(p+1));
  1920.     eai->address_reg = -2;
  1921.     (*pcpp) += 2; p += 2;
  1922.     break;
  1923.  
  1924.      case absl:
  1925.     eai->addr_const_off = (LONG)((*p << 24) | (*(p+1) << 16)
  1926.                    | (*(p+2) << 8) | *(p+3));
  1927.     eai->address_reg = -2;
  1928.     (*pcpp) += 4; p += 4;
  1929.     break;
  1930.  
  1931.      case imm:
  1932.     if (size == sz_long)
  1933.         goto imm2_const;
  1934.     if (size == sz_word)
  1935.         goto imm1_const;
  1936.     
  1937.     /* fall through */
  1938.      case imm0:
  1939.     eai->data_const_off = (BYTE)*(p+1);
  1940.     eai->data_reg = -2;
  1941.     (*pcpp) += 2; p += 2;
  1942.     break;
  1943.  
  1944.      case imm1:
  1945.     imm1_const:
  1946.     eai->data_const_off = (WORD)((*p << 8) | *(p+1));
  1947.     eai->data_reg = -2;
  1948.     (*pcpp) += 2; p += 2;
  1949.     break;
  1950.  
  1951.      case imm2:
  1952.     imm2_const:
  1953.     eai->data_const_off = (LONG)((*p << 24) | (*(p+1) << 16)
  1954.                    | (*(p+2) << 8) | *(p+3));
  1955.     eai->data_reg = -2;
  1956.     (*pcpp) += 4; p += 4;
  1957.     break;
  1958.  
  1959.      case immi:
  1960.     eai->data_const_off = (BYTE)reg;
  1961.     eai->data_reg = -2;
  1962.     break;
  1963.  
  1964.      default:
  1965.     break;
  1966.     }
  1967.     eai->purpose = ea_purpose;
  1968. }
  1969.  
  1970. static int compile_fetchea(struct register_mapping *map, struct ea_info *eai,
  1971.                ULONG *reg_offset)
  1972. {
  1973.     int x86r;
  1974.     ULONG constant;
  1975.     
  1976.     if (eai->data_reg != -1) {
  1977.     *reg_offset = eai->data_const_off;
  1978.     return eai->data_reg;
  1979.     }
  1980.     
  1981.     if (eai->mode == Dreg || eai->mode == Areg || eai->mode == immi || eai->mode == imm
  1982.     || eai->mode == imm0 || eai->mode == imm1 || eai->mode == imm2
  1983.     || eai->address_reg == -1)
  1984.     printf("BUG\n");
  1985.  
  1986.     *reg_offset = 0;
  1987.     if (eai->size == sz_byte)
  1988.     x86r = get_typed_x86_register(map, DATA_X86_REGS);
  1989.     else
  1990.     x86r = get_free_x86_register(map, ALL_X86_REGS);
  1991.     map->x86_locked[x86r]++;
  1992.  
  1993.     compile_force_byteorder(map, eai->address_reg, BO_NORMAL, 0);
  1994.     compile_move_reg_from_mem_regoffs(x86r, eai->address_reg, 
  1995.                       (ULONG)(eai->addr_const_off + address_space),
  1996.                       eai->size);
  1997.     
  1998.     switch (eai->size) {
  1999.      case sz_byte: map->x86_byteorder[x86r] = BO_NORMAL; break;
  2000.      case sz_word: map->x86_byteorder[x86r] = BO_SWAPPED_WORD; break;
  2001.      case sz_long: map->x86_byteorder[x86r] = BO_SWAPPED_LONG; break;
  2002.     }
  2003.     return x86r;
  2004. }
  2005.  
  2006. static void compile_storeea(struct register_mapping *map, struct ea_info *eai,
  2007.                  int valuereg, ULONG valueoffset)
  2008. {
  2009.     ULONG constant;
  2010.     int newr, cacher;
  2011.     
  2012.     if (eai->mode == Dreg) {
  2013.     /* Easy case first: just put the reg in the register cache */
  2014.     if (eai->size == sz_long) {
  2015.         newr = compile_move_const_reg(map, valuereg, &valueoffset, 0);
  2016.         compile_unlock_reg(map, valuereg);
  2017.         if (valueoffset != 0)
  2018.         printf("Hoppla?\n");
  2019.         /*
  2020.          * Two checks whether registers are already in the cache.
  2021.          */
  2022.         if (map->x86_cache_reg[newr] != -1 
  2023.         && (map->x86_cache_reg[newr] != eai->reg
  2024.             || map->x86_cr_type[newr] != 1))
  2025.         {
  2026.         remove_x86r_from_cache(map, newr, 0);
  2027.         }
  2028.         if (map->dreg_map[eai->reg] != -1
  2029.         && map->dreg_map[eai->reg] != newr) 
  2030.         {
  2031.         /* No need to write back */
  2032.         map->x86_cache_reg[map->dreg_map[eai->reg]] = -1;
  2033.         }
  2034.         map->x86_cache_reg[newr] = eai->reg;
  2035.         map->x86_cr_type[newr] = 1;
  2036.         map->x86_const_offset[newr] = valueoffset;
  2037.         map->x86_dirty[newr] = 1;
  2038.         map->dreg_map[eai->reg] = newr;
  2039.         map->x86_verified[newr] = 0;
  2040.         return;
  2041.     }
  2042.     
  2043.     if (eai->data_reg < 0)
  2044.         printf("Don't have a data reg to move to!\n");
  2045.  
  2046.     compile_force_byteorder(map, eai->data_reg, BO_NORMAL, 1);
  2047.     compile_force_byteorder(map, valuereg, BO_NORMAL, 1);
  2048.     map->x86_verified[eai->data_reg] = 0;
  2049.     if (valuereg == -2) {
  2050.         if (eai->size == sz_byte) {
  2051.         if (((1 << eai->data_reg) & DATA_X86_REGS) == 0)
  2052.             printf("Uhoh - not moving to proper type reg\n");
  2053.         assemble(0xB0 + eai->data_reg);
  2054.         assemble(valueoffset);
  2055.         } else {
  2056.         assemble(0x66); assemble(0xB8 + eai->data_reg);
  2057.         assemble_uword(valueoffset);
  2058.         }
  2059.     } else {
  2060.         /* Move the subword into the right place */
  2061. /* This shouldn't be necessary */
  2062. #if 0
  2063.         newr = compile_force_const_reg(map, valuereg, &valueoffset);
  2064. #else
  2065.         newr = valuereg;
  2066. #endif
  2067.         compile_unlock_reg(map, valuereg);
  2068.         compile_move_reg_reg(eai->data_reg, newr, eai->size);
  2069.     }
  2070.     map->x86_dirty[eai->data_reg] = 1;
  2071.     return;
  2072.     } else if (eai->mode == Areg) {
  2073.     if (eai->size != sz_long)
  2074.         printf("Areg put != long\n");
  2075.  
  2076.     newr = compile_force_const_reg(map, valuereg, &valueoffset, 0);
  2077.     compile_unlock_reg(map, valuereg);
  2078.  
  2079.     if (map->x86_cache_reg[newr] != -1 
  2080.         && (map->x86_cache_reg[newr] != eai->reg
  2081.         || map->x86_cr_type[newr] != 0))
  2082.     {
  2083.         remove_x86r_from_cache(map, newr, 0);
  2084.     }
  2085.     if (map->areg_map[eai->reg] != -1
  2086.         && map->areg_map[eai->reg] != newr)
  2087.     {
  2088.         /* No need to write back */
  2089.         map->x86_cache_reg[map->areg_map[eai->reg]] = -1;
  2090.     }
  2091.     map->x86_verified[newr] = 0;
  2092.     map->x86_cache_reg[newr] = eai->reg;
  2093.     map->x86_cr_type[newr] = 0;
  2094.     map->x86_const_offset[newr] = valueoffset;
  2095.     map->x86_dirty[newr] = 1;
  2096.     map->areg_map[eai->reg] = newr;
  2097.     return;
  2098.     }
  2099.  
  2100.     compile_offset_reg(map, valuereg, valueoffset);
  2101.     /* Correct the byteorder */
  2102.     if (valuereg != -2) {
  2103.     switch (eai->size) {
  2104.      case sz_byte: compile_force_byteorder(map, valuereg, BO_NORMAL, 1); break;
  2105.      case sz_word: compile_force_byteorder(map, valuereg, BO_SWAPPED_WORD, 1); break;
  2106.      case sz_long: compile_force_byteorder(map, valuereg, BO_SWAPPED_LONG, 1); break;
  2107.     }
  2108.     } else {
  2109.     switch (eai->size) {
  2110.      case sz_long:
  2111.         valueoffset = (((valueoffset & 0xFF000000) >> 24)
  2112.                | ((valueoffset & 0xFF0000) >> 8)
  2113.                | ((valueoffset & 0xFF00) << 8)
  2114.                | ((valueoffset & 0xFF) << 24));
  2115.         break;
  2116.      case sz_word:
  2117.         valueoffset = (((valueoffset & 0xFF00) >> 8)
  2118.                | ((valueoffset & 0xFF) << 8));
  2119.         break;
  2120.     }
  2121.     }
  2122.     
  2123.     /* We may have the value either in valuereg or in valueoffset by now,
  2124.      * not in both (see call to compile_offset_reg() above) */
  2125.     
  2126.     if (valuereg != -2) {
  2127.     compile_move_reg_to_mem_regoffs(eai->address_reg,
  2128.                     (ULONG)(eai->addr_const_off + address_space),
  2129.                     valuereg, eai->size);
  2130.     } else {
  2131.     /* generate code to move valueoffset,eaoffset(eareg) */
  2132.     switch(eai->size) {                   
  2133.      case sz_byte: assemble(0xC6); break;
  2134.      case sz_word: assemble(0x66); /* fall through */
  2135.      case sz_long: assemble(0xC7); break;
  2136.     }
  2137.     if (eai->address_reg == -2) { /* absolute or PC-relative */
  2138.         assemble(0x05);
  2139.         assemble_long(eai->addr_const_off + address_space);
  2140.     } else {
  2141.         assemble(0x80 + eai->address_reg);
  2142.         assemble_long(eai->addr_const_off + address_space);
  2143.     }
  2144.     switch(eai->size) {
  2145.      case sz_byte: assemble(valueoffset); break;
  2146.      case sz_word: assemble_uword(valueoffset); break;
  2147.      case sz_long: assemble_ulong(valueoffset); break;
  2148.     }
  2149.     }
  2150. }
  2151.  
  2152. #define CE_STACK_SIZE 1000
  2153.  
  2154. static struct {
  2155.     struct register_mapping map;
  2156.     char *jmpoffs;
  2157.     ULONG address;
  2158.     int noflush:1;
  2159. } compile_exit_stack[CE_STACK_SIZE];
  2160.  
  2161. static int cesp;
  2162.  
  2163. static struct register_mapping current_exit_regmap;
  2164.  
  2165. static void generate_exit(struct register_mapping *map, int address)
  2166. {
  2167.     int i;
  2168.     
  2169.     if (map != NULL)
  2170.     sync_reg_cache (map, 1);
  2171.     assemble(0xB8); /* movl $new_pc,%eax */
  2172.     assemble_ulong(address);
  2173.     assemble(0xC3); /* RET */
  2174. }
  2175.  
  2176. static void copy_map_with_undo(struct register_mapping *dst, 
  2177.                    struct register_mapping *src,
  2178.                    struct pid_undo *pud)
  2179. {
  2180.     int i;
  2181.     *dst = *src;
  2182.     for (i = 0; i < pud->used; i++) {
  2183.     int m68kr = pud->m68kr[i];
  2184.     int x86r = pud->x86r[i];
  2185.     int old_cr = dst->areg_map[m68kr];
  2186.     if (old_cr != -1) {
  2187.         dst->x86_cache_reg[old_cr] = -1;
  2188.     }
  2189.     dst->x86_cache_reg[x86r] = m68kr;
  2190.     dst->areg_map[m68kr] = x86r;
  2191.     dst->x86_cr_type[x86r] = 0;
  2192.     dst->x86_const_offset[x86r] = pud->offs[i];
  2193.     dst->x86_dirty[x86r] = pud->dirty[i];
  2194.     }
  2195. }
  2196.  
  2197. static void generate_possible_exit(struct register_mapping *map,
  2198.                    struct ea_info *eai, int iip,
  2199.                    struct pid_undo *pud)
  2200. {
  2201.     struct register_mapping exit_regmap;
  2202.     switch (eai->address_reg) {
  2203.      case -1:
  2204.     /* EA doesn't refer to memory */
  2205.     break;
  2206.      case -2:
  2207.     /* Only a constant offset */
  2208.     eai->addr_const_off &= (1<<24)-1;
  2209.     if (!good_address_map[eai->addr_const_off]) {
  2210.         copy_map_with_undo(&exit_regmap, map, pud);
  2211.         generate_exit(&exit_regmap, insn_info[iip].address);
  2212.     }
  2213.     break;
  2214.      default:
  2215.     if (map->x86_verified[eai->address_reg])
  2216.         break;
  2217.     map->x86_verified[eai->address_reg] = 1;
  2218.     if (cesp == CE_STACK_SIZE) {
  2219.         copy_map_with_undo(&exit_regmap, map, pud);
  2220.         generate_exit(&exit_regmap, insn_info[iip].address);
  2221.         break;
  2222.     }
  2223.     copy_map_with_undo(&compile_exit_stack[cesp].map, map, pud);
  2224.     compile_exit_stack[cesp].address = insn_info[iip].address;
  2225.     assemble(0x80); assemble(0xB8 + eai->address_reg); /* cmpb $0, good_address_map(x86r) */
  2226.     assemble_long(good_address_map + eai->addr_const_off);
  2227.     assemble(0);
  2228.     assemble(0x0F); assemble(0x84); /* JE finish */
  2229.     compile_exit_stack[cesp].jmpoffs = compile_here();
  2230.     compile_exit_stack[cesp].noflush = 0;
  2231.     assemble_ulong(0);
  2232.     cesp++;
  2233.     break;
  2234.     }
  2235. }
  2236.  
  2237. static void finish_exits(void)
  2238. {
  2239.     int i;
  2240.     for (i = 0; i < cesp; i++) {
  2241.     char *exitpoint = compile_here();
  2242.     char *nextpoint;
  2243.  
  2244.     if (compile_exit_stack[i].noflush)
  2245.         generate_exit(NULL, compile_exit_stack[i].address);
  2246.     else
  2247.         generate_exit(&compile_exit_stack[i].map, compile_exit_stack[i].address);
  2248.     nextpoint = compile_here();
  2249.     compile_org(compile_exit_stack[i].jmpoffs);
  2250.     assemble_ulong(exitpoint - (compile_exit_stack[i].jmpoffs + 4));
  2251.     compile_org(nextpoint);
  2252.     }
  2253. }
  2254.  
  2255. static void finish_condjumps(int lastiip)
  2256. {
  2257.     int iip;
  2258.     char *lastptr = compile_here();
  2259.     for (iip = 0; iip < lastiip; iip++) {
  2260.     char *fillin = insn_info[iip].compiled_fillin;
  2261.     if (fillin != NULL) {
  2262.         compile_org(insn_info[iip].compiled_fillin);
  2263.         assemble_ulong(insn_info[insn_info[iip].jumps_to].compiled_jumpaddr - (fillin + 4));
  2264.     }
  2265.     }
  2266.     compile_org(lastptr);
  2267. }
  2268.  
  2269. #define CC_X_FROM_86C 1
  2270. #define CC_C_FROM_86C 2
  2271. #define CC_Z_FROM_86Z 4
  2272. #define CC_V_FROM_86V 8 
  2273. #define CC_N_FROM_86N 16
  2274. #define CC_TEST_REG   32
  2275. #define CC_Z_FROM_86C 64
  2276. #define CC_SAHF       128
  2277. #define CC_TEST_CONST 256
  2278. #define CC_AFTER_RO   512
  2279. #define CC_AFTER_ROX  1024
  2280.  
  2281. #define CC68K_C 16
  2282. #define CC68K_V 8
  2283. #define CC68K_Z 4
  2284. #define CC68K_N 2
  2285. #define CC68K_X 1
  2286.  
  2287. static unsigned int cc_status;
  2288. static int cc_reg;
  2289. static ULONG cc_offset;
  2290. static wordsizes cc_size;
  2291.  
  2292. static void compile_do_cc_test_reg(struct register_mapping *map)
  2293. {
  2294.     compile_force_byteorder(map, cc_reg, BO_NORMAL, 1);
  2295.     if (cc_offset != 0)
  2296.     printf("Pull my finger\n");
  2297.     if (cc_size == sz_word) /* test ccreg */
  2298.     assemble(0x66);
  2299.     if (cc_size == sz_byte)
  2300.     assemble(0x84);
  2301.     else
  2302.     assemble(0x85);
  2303.     assemble(0xC0 + 9*cc_reg);
  2304. }
  2305.  
  2306. static int compile_flush_cc_cache(struct register_mapping *map, int status, 
  2307.                   int live_at_end, int user_follows,
  2308.                   int user_live_at_end, int user_ccval)
  2309. {
  2310.     int status_for_user = 0;
  2311.  
  2312.     if (user_follows) {
  2313.     int need_for_user = 0;
  2314.     int user_flagmask = cc_flagmask(user_ccval);
  2315.  
  2316.     if (user_flagmask & CC68K_C)
  2317.         need_for_user |= CC_C_FROM_86C;
  2318.     if (user_flagmask & CC68K_Z)
  2319.         need_for_user |= CC_Z_FROM_86Z;
  2320.     if (user_flagmask & CC68K_N)
  2321.         need_for_user |= CC_N_FROM_86N;
  2322.     if (user_flagmask & CC68K_V)
  2323.         need_for_user |= CC_V_FROM_86V;
  2324.  
  2325.     /* Check whether we can satisfy the user's needs in a simple way. */
  2326.     if ((need_for_user & status) == need_for_user)
  2327.         status_for_user = status;
  2328.     else if (user_flagmask == CC68K_Z && status == CC_Z_FROM_86C)
  2329.         status_for_user = status;
  2330.     else if (status == CC_TEST_REG && (user_flagmask & (CC68K_C|CC68K_V|CC68K_Z|CC68K_N)) != 0) {
  2331.         if (cc_reg == -2) {
  2332.         status_for_user = CC_TEST_CONST;
  2333.         } else {
  2334.         compile_do_cc_test_reg(map);
  2335.         status_for_user = status = (CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V);
  2336.         }
  2337.     } else if (status == CC_AFTER_RO) {
  2338.         /* We fake some information here... */
  2339.         if (user_flagmask == CC68K_C && (user_live_at_end & ~CC68K_C) == 0)
  2340.         status = status_for_user = CC_C_FROM_86C;
  2341.         else if (((user_flagmask | user_live_at_end) & CC68K_C) == 0) {
  2342.         status = CC_TEST_REG; user_live_at_end = CC68K_Z|CC68K_N|CC68K_V;
  2343.         status_for_user = (CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V);
  2344.         } else
  2345.         status_for_user = CC_SAHF;
  2346.     } else if (status == CC_AFTER_ROX) {
  2347.         if (user_flagmask == CC68K_C && (user_live_at_end & ~(CC68K_C|CC68K_X)) == 0)
  2348.         status = status_for_user = CC_C_FROM_86C;
  2349.         else if (((user_flagmask | user_live_at_end) & (CC68K_C|CC68K_X)) == 0) {
  2350.         status = CC_TEST_REG; user_live_at_end = CC68K_Z|CC68K_N|CC68K_V;
  2351.         status_for_user = (CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V);
  2352.         } else
  2353.         status_for_user = CC_SAHF;
  2354.     } else if (need_for_user != 0) {
  2355.         /* No way to handle it easily */
  2356.         status_for_user = CC_SAHF;
  2357.     }
  2358.     if (status_for_user != CC_SAHF)
  2359.         live_at_end = user_live_at_end;
  2360.     }
  2361.  
  2362.     /*
  2363.      * Now store the flags which are live at the end of this insn and set by 
  2364.      * us into their home locations 
  2365.      */
  2366.     if (status == CC_TEST_REG) {
  2367.     if ((live_at_end & (CC68K_C|CC68K_V|CC68K_Z|CC68K_N)) == 0)
  2368.         goto all_ok;
  2369.  
  2370.     if (cc_reg == -2) {
  2371.         UBYTE f = 0;
  2372.         if (cc_size == sz_byte) {
  2373.         f |= (cc_offset & 0x80) ? 0x80 : 0;
  2374.         f |= (cc_offset & 0xFF) == 0 ? 0x40 : 0;
  2375.         } else if (cc_size == sz_byte) {
  2376.         f |= (cc_offset & 0x8000) ? 0x80 : 0;
  2377.         f |= (cc_offset & 0xFFFF) == 0 ? 0x40 : 0;
  2378.         } else {
  2379.         f |= (cc_offset & 0x80000000) ? 0x80 : 0;
  2380.         f |= (cc_offset & 0xFFFFFFFF) == 0 ? 0x40 : 0;
  2381.         }
  2382.         assemble(0x66); assemble(0xC7); assemble(0x05); 
  2383.         assemble_long((char*)®flags);
  2384.         assemble_uword(f);
  2385.     } else {
  2386.         int tmpr = get_free_x86_register(map, ALL_X86_REGS);
  2387.         compile_do_cc_test_reg(map);
  2388.  
  2389.         /* pushfl; popl tmpr; movl tempr, regflags */
  2390.         assemble(0x9C); assemble(0x58+tmpr);
  2391.         compile_move_reg_to_mem_regoffs(-2, (ULONG)®flags, tmpr, sz_word);
  2392.     }
  2393.     } else if (status == CC_Z_FROM_86C) {
  2394.     if ((live_at_end & CC68K_Z) != 0) {
  2395.         int tmpr = get_typed_x86_register(map, DATA_X86_REGS);
  2396.         assemble(0x9C);
  2397.         /* setnc tmpr; shl $6, tmpr; andb $~0x40, regflags; orb tmpr, regflags */
  2398.         assemble(0x0F); assemble(0x93); assemble(0xC0 + tmpr);
  2399.         assemble(0xC0); assemble(4*8 + 0xC0 + tmpr); assemble(6);
  2400.         assemble(0x80); assemble(0x05+0x20); assemble_long(®flags); assemble((UBYTE)~0x40);
  2401.         assemble(0x08); assemble(0x05+ tmpr*8); assemble_long(®flags);
  2402.         assemble(0x9D);
  2403.     }
  2404.     } else if (status == CC_AFTER_RO || status == CC_AFTER_ROX) {
  2405.     int tmpr = get_typed_x86_register(map, DATA_X86_REGS);
  2406.     assemble(0x9C);
  2407.     compile_do_cc_test_reg(map);
  2408.     /* pushfl; popl tmpr; movl tempr, regflags */
  2409.     assemble(0x9C); assemble(0x58+tmpr);
  2410.     assemble(0x9D);
  2411.     /* adc $0, tmpr */
  2412.     assemble(0x80); assemble(0xC0 + tmpr + 8*2); assemble(0);
  2413.     compile_move_reg_to_mem_regoffs(-2, (ULONG)®flags, tmpr, sz_word);
  2414.     if (status == CC_AFTER_ROX)
  2415.         compile_move_reg_to_mem_regoffs(-2, 2 + (ULONG)®flags, tmpr, sz_word);
  2416.     } else if (status != 0) {
  2417.     assert((status & CC_TEST_REG) == 0);
  2418.     assert (status == (CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_X_FROM_86C | CC_V_FROM_86V)
  2419.         || status == (CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V)
  2420.         || status == CC_C_FROM_86C);
  2421.         
  2422.     if ((status & CC_X_FROM_86C) == 0)
  2423.         live_at_end &= ~CC68K_X;
  2424.     
  2425.     if (status == CC_C_FROM_86C && (live_at_end & CC68K_C) != 0) 
  2426.         fprintf(stderr, "Shouldn't be needing C here!\n");
  2427.     else if (live_at_end) {
  2428.         if ((live_at_end & CC68K_X) == 0)
  2429.         status &= ~CC_X_FROM_86C;
  2430.  
  2431.         if (live_at_end) {
  2432.         int tmpr = get_free_x86_register(map, ALL_X86_REGS);
  2433.         /* pushfl; popl tmpr; movl tempr, regflags */
  2434.         assemble(0x9C); assemble(0x58+tmpr);
  2435.         compile_move_reg_to_mem_regoffs(-2, (ULONG)®flags, tmpr, sz_word);
  2436.         
  2437.         if (status & CC_X_FROM_86C) {
  2438.             compile_move_reg_to_mem_regoffs(-2, 2 + (ULONG)®flags, tmpr, sz_word);
  2439.         }
  2440.         }
  2441.     }
  2442.     }
  2443.  
  2444.     all_ok:
  2445.     return status_for_user;
  2446. }
  2447.     
  2448. static char *compile_condbranch(struct register_mapping *map, int iip,
  2449.                 int new_cc_status)
  2450. {
  2451.     int cc = insn_info[iip].dp->cc;
  2452.     int flagsused = cc_flagmask(cc);
  2453.     int flagsneeded = 0;
  2454.     char *undo_pointer = compile_here();
  2455.  
  2456.     if (flagsused & CC68K_C)
  2457.     flagsneeded |= CC_C_FROM_86C;
  2458.     if (flagsused & CC68K_Z)
  2459.     flagsneeded |= CC_Z_FROM_86Z;
  2460.     if (flagsused & CC68K_N)
  2461.     flagsneeded |= CC_N_FROM_86N;
  2462.     if (flagsused & CC68K_V)
  2463.     flagsneeded |= CC_V_FROM_86V;
  2464.  
  2465.     if (new_cc_status == CC_SAHF) {
  2466.     int tmpr = get_free_x86_register(map, ALL_X86_REGS);
  2467.     compile_move_reg_from_mem_regoffs(tmpr, -2, (ULONG)®flags, sz_long);
  2468.     assemble(0x66); assemble(0x50+tmpr); assemble(0x66); assemble(0x9D);
  2469.     new_cc_status = CC_C_FROM_86C|CC_Z_FROM_86Z|CC_N_FROM_86N|CC_V_FROM_86V;
  2470.     } else if (new_cc_status == CC_TEST_CONST) {
  2471.     int n,z;
  2472.     switch(cc_size) {
  2473.      case sz_byte: n = ((BYTE)cc_offset) < 0; z = ((BYTE)cc_offset) == 0; break;
  2474.      case sz_word: n = ((WORD)cc_offset) < 0; z = ((WORD)cc_offset) == 0; break;
  2475.      case sz_long: n = ((LONG)cc_offset) < 0; z = ((LONG)cc_offset) == 0; break;
  2476.     }
  2477. #define Bcc_TRUE 0
  2478. #define Bcc_FALSE 1
  2479.     flagsneeded = 0;
  2480.     new_cc_status = 0;
  2481.     switch (cc) {
  2482.      case 2: cc = !z ? Bcc_TRUE : Bcc_FALSE; break; /* !CFLG && !ZFLG */
  2483.      case 3: cc = z ? Bcc_TRUE : Bcc_FALSE; break; /* CFLG || ZFLG */
  2484.      case 4: cc = Bcc_TRUE; break; /* !CFLG */
  2485.      case 5: cc = Bcc_FALSE; break; /* CFLG */
  2486.      case 6: cc = !z ? Bcc_TRUE : Bcc_FALSE; break; /* !ZFLG */
  2487.      case 7: cc = z ? Bcc_TRUE : Bcc_FALSE; break; /* ZFLG */
  2488.      case 8: cc = Bcc_TRUE; break; /* !VFLG */
  2489.      case 9: cc = Bcc_FALSE; break; /* VFLG */
  2490.      case 10:cc = !n ? Bcc_TRUE : Bcc_FALSE; break; /* !NFLG */
  2491.      case 11:cc = n ? Bcc_TRUE : Bcc_FALSE; break; /* NFLG */
  2492.      case 12:cc = !n ? Bcc_TRUE : Bcc_FALSE; break; /* NFLG == VFLG */
  2493.      case 13:cc = n ? Bcc_TRUE : Bcc_FALSE; break; /* NFLG != VFLG */
  2494.      case 14:cc = !n && !z ? Bcc_TRUE : Bcc_FALSE; break; /* !ZFLG && (NFLG == VFLG) */
  2495.      case 15:cc = n || z ? Bcc_TRUE : Bcc_FALSE; break; /* ZFLG || (NFLG != VFLG) */
  2496.     }
  2497.     } else if (new_cc_status == CC_Z_FROM_86C) {
  2498.     if (cc == 6 || cc == 7) {
  2499.         cc = (cc - 2) ^ 1;
  2500.         /* Fake... */
  2501.         flagsneeded = new_cc_status = CC_C_FROM_86C;
  2502.     } else if (cc != 0 && cc != 1)
  2503.         printf("Groan!\n");
  2504.     }
  2505.     
  2506.     if (cc == 1)
  2507.     return NULL;
  2508.     
  2509.     if ((flagsneeded & new_cc_status) == flagsneeded) {
  2510.     char *result;
  2511.     /* We can generate a simple branch */
  2512.     if (cc == 0)
  2513.         assemble(0xE9);
  2514.     else
  2515.         assemble(0x0F);
  2516.     switch(cc) {
  2517.      case 2: assemble(0x87); break;          /* HI */
  2518.      case 3: assemble(0x86); break;          /* LS */
  2519.      case 4: assemble(0x83); break;          /* CC */
  2520.      case 5: assemble(0x82); break;          /* CS */
  2521.      case 6: assemble(0x85); break;          /* NE */
  2522.      case 7: assemble(0x84); break;          /* EQ */
  2523.      case 8: assemble(0x81); break;          /* VC */
  2524.      case 9: assemble(0x80); break;          /* VS */
  2525.      case 10:assemble(0x89); break;          /* PL */
  2526.      case 11:assemble(0x88); break;          /* MI */
  2527.      case 12:assemble(0x8D); break;          /* GE */
  2528.      case 13:assemble(0x8C); break;          /* LT */
  2529.      case 14:assemble(0x8F); break;          /* GT */
  2530.      case 15:assemble(0x8E); break;          /* LE */
  2531.     }
  2532.     result = compile_here();
  2533.     assemble_ulong(0);
  2534.     return result;
  2535.     }
  2536.     printf("Uhhuh.\n");
  2537.     return NULL;
  2538. }
  2539.  
  2540. static void compile_handle_bcc(struct register_mapping *map, int iip, 
  2541.                    int new_cc_status)
  2542. {
  2543.     insn_info[iip].compiled_fillin = compile_condbranch(map, iip, new_cc_status);
  2544. }
  2545.  
  2546. static void compile_handle_dbcc(struct register_mapping *map, int iip, 
  2547.                 int new_cc_status, int dreg)
  2548. {
  2549.     int cc = insn_info[iip].dp->cc;
  2550.     int flagsused = cc_flagmask(cc);
  2551.     int flagsneeded = 0;
  2552.     char *undo_pointer = compile_here();
  2553.     char *fillin1 = compile_condbranch(map, iip, new_cc_status);
  2554.     
  2555.     /* subw $1,dreg; jnc ... */
  2556.     assemble(0x66); assemble(0x83); assemble(0x05 + 5*8);
  2557.     assemble_long(regs.d + dreg);
  2558.     assemble(1);
  2559.     assemble(0x0F); assemble(0x83);
  2560.     insn_info[iip].compiled_fillin = compile_here();
  2561.     assemble_ulong(0);
  2562.     if (fillin1 != NULL) {
  2563.     char *oldp = compile_here();
  2564.     compile_org(fillin1);
  2565.     assemble_ulong(oldp - (fillin1+4));
  2566.     compile_org(oldp);
  2567.     }
  2568. }
  2569.  
  2570. static void handle_bit_insns(struct register_mapping *map, struct ea_info *srcea,
  2571.                  struct ea_info *dstea, instrmnem optype)
  2572. {
  2573.     int srcreg, dstreg, dstreg2;
  2574.     ULONG srcoffs, dstoffs;
  2575.     int code = (optype == i_BTST ? 0
  2576.         : optype == i_BSET ? 1
  2577.         : optype == i_BCLR ? 2
  2578.         : /* optype == i_BCHG */ 3);
  2579.  
  2580.     srcreg = compile_fetchea(map, srcea, &srcoffs);
  2581.     if (srcreg >= 0) {
  2582.     compile_offset_reg(map, srcreg, srcoffs);
  2583.     srcoffs = 0;
  2584.     }
  2585.     /* Fake some EA info... */
  2586.     if (dstea->data_reg == -2) {
  2587.     dstreg2 = compile_fetchea(map, dstea, &dstoffs);
  2588.     dstreg = compile_move_const_reg(map, dstreg2, &dstoffs, 0);
  2589.     compile_unlock_reg(map, dstreg2);
  2590.     dstea->data_const_off = 0;
  2591.     dstea->data_reg = dstreg;
  2592.     } else if (dstea->data_reg >= 0) {
  2593.     compile_offset_reg(map, dstea->data_reg, dstea->data_const_off);
  2594.     dstea->data_const_off = 0;
  2595.     }
  2596.     compile_force_byteorder(map, srcreg, BO_NORMAL, 0);
  2597.     if (srcreg != -2) {
  2598.     remove_x86r_from_cache(map, srcreg, 0);
  2599.     /* andl $something,srcreg */
  2600.     assemble(0x83); assemble(0xC0 + 4*8 + srcreg);
  2601.     if (dstea->size == sz_byte)
  2602.         assemble(7);
  2603.     else
  2604.         assemble(31);
  2605.     } else
  2606.     if (dstea->size == sz_byte)
  2607.         srcoffs &= 7;
  2608.     else
  2609.         srcoffs &= 31;
  2610.  
  2611.     /* Areg isn't possible here */
  2612.     if (dstea->mode == Dreg && dstea->data_reg == -1) {
  2613.     if (srcreg == -2) {
  2614.         assemble(0x0F); assemble(0xBA); assemble(5 + 8*(4 + code));
  2615.         assemble_long(regs.d + dstea->reg);
  2616.         assemble(srcoffs);
  2617.     } else {
  2618.         assemble(0x0F); assemble(0xA3 + 8*code);
  2619.         assemble(5 + srcreg*8);
  2620.         assemble_long(regs.d + dstea->reg);
  2621.     }
  2622.     } else if (dstea->data_reg >= 0) {
  2623.     compile_force_byteorder(map, dstea->data_reg, BO_NORMAL, 0);
  2624.     if (srcreg == -2) {
  2625.         assemble(0x0F); assemble(0xBA); assemble(0xC0 + dstea->data_reg + 8*(4 + code));
  2626.         assemble(srcoffs);
  2627.     } else {
  2628.         assemble(0x0F); assemble(0xA3 + 8*code);
  2629.         assemble(0xC0 + dstea->data_reg + srcreg*8);
  2630.     }
  2631.     if (optype != i_BTST)
  2632.         map->x86_dirty[dstea->data_reg] = 1;
  2633.     } else {
  2634.     int addr_code = dstea->address_reg == -2 ? 5 : dstea->address_reg + 0x80;
  2635.     /* We have an address in memory */
  2636.     if (dstea->data_reg != -1)
  2637.         printf("Things don't look good in handle_bit_insns\n");
  2638.     if (srcreg == -2) {
  2639.         assemble(0x0F); assemble(0xBA); 
  2640.         assemble(addr_code + 8*(4 + code));
  2641.         assemble_long(address_space + dstea->addr_const_off);
  2642.         assemble(srcoffs);
  2643.     } else {
  2644.         assemble(0x0F); assemble(0xA3 + 8*code);
  2645.         assemble(addr_code + srcreg*8);
  2646.         assemble_long(address_space + dstea->addr_const_off);
  2647.     }
  2648.     
  2649.     }
  2650.     cc_status = CC_Z_FROM_86C;
  2651. }
  2652.  
  2653. static int do_rotshi = 1;
  2654.  
  2655. static void handle_rotshi(struct register_mapping *map, int iip, 
  2656.               UBYTE *realpc, CPTR current_addr)
  2657. {
  2658.     struct pid_undo pub;
  2659.     struct ea_info eai;
  2660.     int amode_reg = insn_info[iip].dp->sreg;
  2661.     int amode_mode = insn_info[iip].dp->smode;
  2662.     wordsizes size = insn_info[iip].dp->size;
  2663.     int shiftcount;
  2664.     int mnemo = insn_info[iip].dp->mnemo;
  2665.     int shiftcode;
  2666.  
  2667.     int srcreg, srcreg2;
  2668.     ULONG srcoffs;
  2669.     
  2670.     switch(mnemo) {
  2671.      case i_ASLW: shiftcount = 1; mnemo = i_ASL; break;
  2672.      case i_ASRW: shiftcount = 1; mnemo = i_ASR; break;
  2673.      case i_LSLW: shiftcount = 1; mnemo = i_LSL; break;
  2674.      case i_LSRW: shiftcount = 1; mnemo = i_LSR; break;
  2675.      case i_ROLW: shiftcount = 1; mnemo = i_ROL; break;
  2676.      case i_RORW: shiftcount = 1; mnemo = i_ROR; break;
  2677.      case i_ROXLW:shiftcount = 1; mnemo = i_ROXL;break;
  2678.      case i_ROXRW:shiftcount = 1; mnemo = i_ROXR;break;
  2679.      default:
  2680.     if (insn_info[iip].dp->smode != immi) {
  2681.         generate_exit(map, insn_info[iip].address);
  2682.         return;
  2683.     }
  2684.     amode_reg = insn_info[iip].dp->dreg;
  2685.     amode_mode = insn_info[iip].dp->dmode;
  2686.     shiftcount = insn_info[iip].dp->sreg;
  2687.     break;
  2688.     }
  2689.     if ((mnemo == i_LSL || mnemo == i_LSR || mnemo == i_ASR || mnemo == i_ASL)
  2690.     && (insn_info[iip].flags_live_at_end & CC68K_V) != 0) {
  2691.     generate_exit(map, insn_info[iip].address);
  2692.     return;
  2693.     }
  2694.     if (mnemo == i_ROR || mnemo == i_ROL || mnemo == i_ROXR || mnemo == i_ROXL) {
  2695.     if ((insn_info[iip].flags_live_at_end & CC68K_V) != 0) {
  2696.         generate_exit(map, insn_info[iip].address);
  2697.         return;
  2698.     }
  2699.     }
  2700.     if (mnemo == i_ROXR || mnemo == i_ROXL) {
  2701.     remove_x86r_from_cache(map, r_EAX, 1);
  2702.     map->x86_locked[r_EAX]++;
  2703.     compile_move_reg_from_mem_regoffs(r_AH, -2, 2 + (ULONG)®flags,
  2704.                       sz_byte);
  2705.     }
  2706.     compile_prepareea(map, amode_mode, amode_reg, size,
  2707.               &realpc, current_addr,
  2708.               &eai, EA_LOAD|EA_STORE, &pub, 1);
  2709.     
  2710.     generate_possible_exit(map, &eai, iip, &pub);
  2711.     
  2712.     srcreg = compile_fetchea(map, &eai, &srcoffs);
  2713.     srcreg2 = compile_move_const_reg(map, srcreg, &srcoffs, insn_info[iip].dp->size == sz_byte ? DATA_X86_REGS : 0);
  2714.     compile_unlock_reg(map, srcreg);
  2715.  
  2716.     compile_force_byteorder(map, srcreg2, BO_NORMAL, 0);
  2717.  
  2718.     switch (mnemo) {
  2719.      case i_ASL:
  2720.     shiftcode = 4; cc_status = CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V | CC_X_FROM_86C;
  2721.     break;
  2722.      case i_LSL:
  2723.     shiftcode = 4; cc_status = CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V | CC_X_FROM_86C;
  2724.     break;    
  2725.      case i_LSR:
  2726.     shiftcode = 5; cc_status = CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V | CC_X_FROM_86C;
  2727.     break;
  2728.      case i_ASR:
  2729.     shiftcode = 7; cc_status = CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V | CC_X_FROM_86C;
  2730.     break;
  2731.      case i_ROR:
  2732.     shiftcode = 1; cc_status = CC_AFTER_RO;
  2733.     break;
  2734.      case i_ROL:
  2735.     shiftcode = 0; cc_status = CC_AFTER_RO;
  2736.     break;
  2737.      case i_ROXL:
  2738.     shiftcode = 2; assemble(0x9E); /* SAHF */ cc_status = CC_AFTER_ROX;
  2739.     break;
  2740.      case i_ROXR:
  2741.     shiftcode = 3; assemble(0x9E); /* SAHF */ cc_status = CC_AFTER_ROX;
  2742.     break;
  2743.     }
  2744.  
  2745.     if (size == sz_word)
  2746.     assemble(0x66);
  2747.     assemble((shiftcount == 1 ? 0xD0 : 0xC0) + (size == sz_byte ? 0 : 1));
  2748.     assemble(shiftcode*8+0xC0 + srcreg);
  2749.     if (shiftcount != 1) assemble(shiftcount);
  2750.     cc_offset = 0; cc_size = size; cc_reg = srcreg;
  2751.     
  2752.     compile_storeea(map, &eai, srcreg, 0);
  2753. }
  2754.  
  2755. static ULONG testmask = 0xF80000, testval = 0xF80000;
  2756.  
  2757. static int m68k_compile_block(struct hash_block *hb)
  2758. {
  2759.     int movem_extra = 0;
  2760.     int last_iip = m68k_scan_block(hb, &movem_extra);
  2761.     struct register_mapping map;
  2762.     int i, iip, szflag;
  2763.     UBYTE *realpc_start = NULL;
  2764.     struct bb_info *current_bb;
  2765.     int cc_status_for_bcc = CC_SAHF;
  2766.     
  2767.     cesp = 0;
  2768.  
  2769.     if (n_compiled > n_max_comp)
  2770.     return 1;
  2771.     else if (n_compiled++ == n_max_comp)
  2772.     printf("X\n");
  2773.  
  2774.     cc_status = 0; compile_failure = 0;
  2775.  
  2776.     /* Kickstart ROM address? */
  2777.     if ((hb->he_first->addr & 0xF80000) != 0xF80000
  2778.     && 0 && !patched_syscalls)
  2779.     return 1;
  2780.  
  2781.     if (alloc_code (hb, last_iip + movem_extra) == NULL) {
  2782.     hb->allocfailed = 1;
  2783.     return 0;
  2784.     }
  2785.     compile_org(hb->compile_start);
  2786.     compile_last_addr = (char *)hb->compile_start + hb->alloclen;
  2787.     
  2788.     /* m68k_scan_block() will leave this all set up */
  2789.     current_bb = bb_stack;
  2790.     
  2791.     for (i = 0; i < 8; i++) {
  2792.     map.dreg_map[i] = map.areg_map[i] = -1;
  2793.     map.x86_dirty[i] = 0;
  2794.     map.x86_cache_reg[i] = -1;
  2795.     map.x86_cr_type[i] = 0;
  2796.     map.x86_const_offset[i] = 0;
  2797.     map.x86_verified[i] = 0;
  2798.     map.x86_byteorder[i] = BO_NORMAL;
  2799.     }
  2800.     
  2801.     for (iip = 0; iip < last_iip && !compile_failure; iip++) {
  2802.     UBYTE *realpc;
  2803.     int srcreg, dstreg, srcreg2, dstreg2;
  2804.     ULONG srcoffs, dstoffs;
  2805.     struct ea_info eainfo[4];
  2806.     CPTR current_addr;
  2807.     struct pid_undo pub;
  2808.     
  2809.     /* Set up locks for a new insn. We don't bother to clear this
  2810.      * properly after compiling one insn. */
  2811.     for (i = 0; i < 8; i++)
  2812.         map.x86_locked[i] = i == r_ESP ? 1 : 0;
  2813.  
  2814.     pub.used = 0;
  2815.     current_addr = insn_info[iip].address + 2;
  2816.  
  2817.     if (iip == current_bb->first_iip) {
  2818.         sync_reg_cache(&map, 1);
  2819.         if (!quiet_compile)
  2820.         printf("Compiling %08lx\n", current_bb->h->addr);
  2821.         realpc_start = get_real_address(current_bb->h->addr);
  2822.         current_bb->h->execute = (code_execfunc)compile_here();
  2823.         current_bb->h->matchword = *(ULONG *)realpc_start;
  2824.         cc_status_for_bcc = CC_SAHF;
  2825.     }
  2826.  
  2827.     realpc = realpc_start + (current_addr - current_bb->h->addr);    
  2828.  
  2829.     insn_info[iip].compiled_jumpaddr = compile_here();        
  2830.     insn_info[iip].compiled_fillin = NULL;
  2831.     
  2832.     if (insn_info[iip].jump_target) {
  2833.         if (cesp == CE_STACK_SIZE) {
  2834.         generate_exit(NULL, insn_info[iip].address);
  2835.         compile_failure = 1;
  2836.         } else {
  2837.         assemble(0xFE); assemble(0x05 + 8*1); assemble_long(&nr_bbs_to_run);
  2838.         assemble(0x0F); assemble(0x84); /* JE finish */
  2839.         compile_exit_stack[cesp].noflush = 1;
  2840.         compile_exit_stack[cesp].address = current_bb->h;
  2841.         compile_exit_stack[cesp].jmpoffs = compile_here();
  2842.         assemble_ulong(0);
  2843.         cesp++;
  2844.         }
  2845.     }
  2846.     /*
  2847.      * This will sort out all insns we can't compile, including
  2848.      * conditional branches and jumps out of this block */
  2849.     if (insn_info[iip].stop_translation == 1) {
  2850.         generate_exit(&map, insn_info[iip].address);
  2851.         cc_status = 0;
  2852.     } else switch (insn_info[iip].dp->mnemo) {
  2853.      case i_Bcc:
  2854.         sync_reg_cache(&map, 0);
  2855.         compile_handle_bcc(&map, iip, cc_status_for_bcc);
  2856.         cc_status = 0;
  2857.         break;
  2858.  
  2859.      case i_DBcc:
  2860.         sync_reg_cache(&map, 0);
  2861.         remove_x86r_from_cache(&map, map.dreg_map[insn_info[iip].dp->sreg], 1);
  2862.         compile_handle_dbcc(&map, iip, cc_status_for_bcc,
  2863.                 insn_info[iip].dp->sreg);
  2864.         cc_status = 0;
  2865.         break;
  2866. #if 0
  2867.      case i_Scc:
  2868.         compile_prepareea(&map, insn_info[iip].dp->smode,
  2869.                   insn_info[iip].dp->sreg, 
  2870.                   insn_info[iip].dp->size, &realpc, current_addr,
  2871.                   eainfo, EA_STORE, &pub, 1);
  2872.  
  2873.         generate_possible_exit(&map, eainfo, iip, &pub);
  2874.         srcreg2 = get_;
  2875.         compile_storeea(&map, eainfo + 0, -2, 0);
  2876.  
  2877.         cc_status = 0;
  2878.         break;
  2879. #endif
  2880.      case i_ADD:
  2881.      case i_SUB:
  2882.      case i_CMP:
  2883.      case i_CMPM:
  2884.         compile_prepareea(&map, insn_info[iip].dp->smode,
  2885.                   insn_info[iip].dp->sreg, 
  2886.                   insn_info[iip].dp->size, &realpc, current_addr,
  2887.                   eainfo, EA_LOAD, &pub, 1);
  2888.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  2889.                   insn_info[iip].dp->dreg, 
  2890.                   insn_info[iip].dp->size, &realpc, current_addr,
  2891.                   eainfo + 1, EA_IN_REG | EA_LOAD | EA_STORE, 
  2892.                   &pub, 1);
  2893.  
  2894.         generate_possible_exit(&map, eainfo, iip, &pub);
  2895.         generate_possible_exit(&map, eainfo+1, iip, &pub);
  2896.         
  2897.         szflag = insn_info[iip].dp->size == sz_byte ? 0 : 1;
  2898.         srcreg = compile_fetchea(&map, eainfo + 0, &srcoffs);
  2899.         dstreg = compile_fetchea(&map, eainfo + 1, &dstoffs);
  2900.         
  2901.         srcreg2 = compile_move_const_reg(&map, srcreg, &srcoffs, insn_info[iip].dp->size == sz_byte ? DATA_X86_REGS : 0);
  2902.         compile_unlock_reg(&map, srcreg);
  2903.         compile_offset_reg(&map, dstreg, dstoffs);
  2904.  
  2905.         compile_force_byteorder(&map, srcreg2, BO_NORMAL, 0);
  2906.         compile_force_byteorder(&map, dstreg, BO_NORMAL, 0);
  2907.  
  2908.         if (insn_info[iip].dp->size == sz_word)
  2909.         assemble(0x66);
  2910.         switch (insn_info[iip].dp->mnemo) {
  2911.          case i_ADD: assemble(0x00+szflag); break;
  2912.          case i_SUB: assemble(0x28+szflag); break;
  2913.          case i_AND: assemble(0x20+szflag); break;
  2914.          case i_EOR: assemble(0x30+szflag); break;
  2915.          case i_CMP: case i_CMPM: assemble(0x38+szflag); break;
  2916.          case i_OR: assemble(0x08+szflag); break;
  2917.         }
  2918.         assemble(0xC0 + srcreg2*8 + dstreg);
  2919.         if ((insn_info[iip].dp->mnemo != i_CMP)
  2920.         && (insn_info[iip].dp->mnemo != i_CMPM))
  2921.         compile_storeea(&map, eainfo + 1, dstreg, 0);
  2922.         switch (insn_info[iip].dp->mnemo) {
  2923.          case i_ADD:
  2924.          case i_SUB:
  2925.         cc_status = CC_X_FROM_86C | CC_Z_FROM_86Z |CC_C_FROM_86C |CC_V_FROM_86V |CC_N_FROM_86N;
  2926.         break;
  2927.          case i_AND:
  2928.          case i_EOR:
  2929.          case i_OR:
  2930.          case i_CMP:
  2931.          case i_CMPM:
  2932.         cc_status = CC_Z_FROM_86Z |CC_C_FROM_86C |CC_V_FROM_86V |CC_N_FROM_86N;
  2933.         break;
  2934.         }
  2935.         break;
  2936.  
  2937.      case i_ADDX:
  2938.      case i_SUBX:
  2939.         compile_prepareea(&map, insn_info[iip].dp->smode,
  2940.                   insn_info[iip].dp->sreg, 
  2941.                   insn_info[iip].dp->size, &realpc, current_addr,
  2942.                   eainfo, EA_LOAD, &pub, 1);
  2943.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  2944.                   insn_info[iip].dp->dreg, 
  2945.                   insn_info[iip].dp->size, &realpc, current_addr,
  2946.                   eainfo + 1, EA_IN_REG | EA_LOAD | EA_STORE, 
  2947.                   &pub, 1);
  2948.  
  2949.         generate_possible_exit(&map, eainfo, iip, &pub);
  2950.         generate_possible_exit(&map, eainfo+1, iip, &pub);
  2951.         
  2952.         szflag = insn_info[iip].dp->size == sz_byte ? 0 : 1;
  2953.         srcreg = compile_fetchea(&map, eainfo + 0, &srcoffs);
  2954.         dstreg = compile_fetchea(&map, eainfo + 1, &dstoffs);
  2955.         
  2956.         srcreg2 = compile_move_const_reg(&map, srcreg, &srcoffs, insn_info[iip].dp->size == sz_byte ? DATA_X86_REGS : 0);
  2957.         compile_unlock_reg(&map, srcreg);
  2958.         compile_offset_reg(&map, dstreg, dstoffs);
  2959.  
  2960.         compile_force_byteorder(&map, srcreg2, BO_NORMAL, 0);
  2961.         compile_force_byteorder(&map, dstreg, BO_NORMAL, 0);
  2962.  
  2963.         /* bt $16, regflags ; get carry */
  2964.         assemble(0x0F); assemble(0xBA); assemble(0x5+4*8); 
  2965.         assemble_long(®flags); assemble(0x10);
  2966.         if (insn_info[iip].dp->size == sz_word)
  2967.         assemble(0x66);
  2968.         switch (insn_info[iip].dp->mnemo) {
  2969.          case i_ADDX: assemble(0x10+szflag); break;
  2970.          case i_SUBX: assemble(0x18+szflag); break;
  2971.         }
  2972.         assemble(0xC0 + srcreg2*8 + dstreg);
  2973.         compile_storeea(&map, eainfo + 1, dstreg, 0);
  2974.         if (insn_info[iip].flags_live_at_end & CC68K_Z) {
  2975.         /* Darn. */
  2976.         int tmpr = get_free_x86_register(&map, ALL_X86_REGS);
  2977.         /* pushfl; popl tmpr */
  2978.         assemble(0x9C); assemble(0x58+tmpr);
  2979.         /* Magic! */
  2980.         /* andl tmpr, regflags; andl $~0x40,tmpr; orl tmpr, regflags */
  2981.         assemble(0x21); assemble(0x05 + 8*tmpr); assemble_long(®flags);
  2982.         assemble(0x81); assemble(0xC0 + 8*4 + tmpr); assemble_ulong(~0x40);
  2983.         assemble(0x09); assemble(0x05 + 8*tmpr); assemble_long(®flags);
  2984.         compile_move_reg_to_mem_regoffs(-2, 2 + (ULONG)®flags, tmpr, sz_word);
  2985.         cc_status = 0;
  2986.         } else {
  2987.         /* Lies! */
  2988.         cc_status = CC_X_FROM_86C | CC_Z_FROM_86Z |CC_C_FROM_86C |CC_V_FROM_86V |CC_N_FROM_86N;
  2989.         }
  2990.         break;
  2991.  
  2992.      case i_MULU:
  2993.      case i_MULS:
  2994.         compile_prepareea(&map, insn_info[iip].dp->smode,
  2995.                   insn_info[iip].dp->sreg, 
  2996.                   insn_info[iip].dp->size, &realpc, current_addr,
  2997.                   eainfo, EA_LOAD, &pub, 1);
  2998.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  2999.                   insn_info[iip].dp->dreg, 
  3000.                   insn_info[iip].dp->size, &realpc, current_addr,
  3001.                   eainfo + 1, EA_IN_REG | EA_LOAD | EA_STORE, 
  3002.                   &pub, 1);
  3003.  
  3004.         generate_possible_exit(&map, eainfo, iip, &pub);
  3005.         generate_possible_exit(&map, eainfo+1, iip, &pub);
  3006.         
  3007.         srcreg = compile_fetchea(&map, eainfo + 0, &srcoffs);
  3008.         dstreg = compile_fetchea(&map, eainfo + 1, &dstoffs);
  3009.         
  3010.         srcreg2 = compile_move_const_reg(&map, srcreg, &srcoffs, insn_info[iip].dp->size == sz_byte ? DATA_X86_REGS : 0);
  3011.         compile_unlock_reg(&map, srcreg);
  3012.         compile_offset_reg(&map, dstreg, dstoffs);
  3013.  
  3014.         compile_force_byteorder(&map, srcreg2, BO_NORMAL, 0);
  3015.         compile_force_byteorder(&map, dstreg, BO_NORMAL, 0);
  3016.  
  3017.         /* Extend the regs properly */
  3018.         remove_x86r_from_cache(&map, srcreg2, 0);
  3019.         switch (insn_info[iip].dp->mnemo) {
  3020.          case i_MULU:
  3021.         assemble(0x81); assemble(0xC0+4*8+srcreg2); assemble_ulong(0xFFFF);
  3022.         assemble(0x81); assemble(0xC0+4*8+dstreg); assemble_ulong(0xFFFF);
  3023.         break;
  3024.          case i_MULS:
  3025.         assemble(0x0F); assemble(0xBF); assemble(0xC0 + 9*srcreg2);
  3026.         assemble(0x0F); assemble(0xBF); assemble(0xC0 + 9*dstreg);
  3027.         break;
  3028.         }
  3029.         /* and multiply */
  3030.         assemble(0x0F); assemble(0xAF); assemble(0xC0 + 8*dstreg + srcreg2);
  3031.         compile_storeea(&map, eainfo + 1, dstreg, 0);
  3032.         cc_status = CC_TEST_REG;
  3033.         cc_reg = dstreg;
  3034.         cc_offset = 0;
  3035.         cc_size = sz_long;
  3036.         break;
  3037.  
  3038.      case i_ADDA:
  3039.      case i_SUBA:
  3040.      case i_CMPA:
  3041.         compile_prepareea(&map, insn_info[iip].dp->smode,
  3042.                   insn_info[iip].dp->sreg, 
  3043.                   insn_info[iip].dp->size, &realpc, current_addr,
  3044.                   eainfo, EA_LOAD, &pub, 1);
  3045.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  3046.                   insn_info[iip].dp->dreg, 
  3047.                   sz_long, &realpc, current_addr,
  3048.                   eainfo + 1, EA_IN_REG | EA_LOAD | EA_STORE, 
  3049.                   &pub, 1);
  3050.  
  3051.         generate_possible_exit(&map, eainfo, iip, &pub);
  3052.  
  3053.         srcreg2 = compile_fetchea(&map, eainfo + 0, &srcoffs);
  3054.         dstreg = compile_fetchea(&map, eainfo + 1, &dstoffs);
  3055.         srcreg = compile_move_const_reg(&map, srcreg2, &srcoffs, 0);
  3056.         compile_unlock_reg(&map, srcreg2);
  3057.         srcreg2 = compile_extend_long(&map, srcreg, &srcoffs, eainfo[0].size);
  3058.         compile_unlock_reg(&map, srcreg);
  3059.         compile_offset_reg(&map, dstreg, dstoffs);
  3060.  
  3061.         compile_force_byteorder(&map, srcreg2, BO_NORMAL, 0);
  3062.         compile_force_byteorder(&map, dstreg, BO_NORMAL, 0);
  3063.  
  3064.         switch (insn_info[iip].dp->mnemo) {
  3065.          case i_ADDA: assemble(0x01); break;
  3066.          case i_SUBA: assemble(0x29); break;
  3067.          case i_CMPA: assemble(0x39); break;
  3068.         }
  3069.         assemble(0xC0 + srcreg2*8 + dstreg);
  3070.  
  3071.         if (insn_info[iip].dp->mnemo == i_CMPA) {
  3072.         cc_status = CC_Z_FROM_86Z |CC_C_FROM_86C |CC_V_FROM_86V |CC_N_FROM_86N;
  3073.         } else {
  3074.         compile_storeea(&map, eainfo + 1, dstreg, 0);
  3075.         cc_status = 0;
  3076.         }
  3077.         break;
  3078.  
  3079.      case i_MOVE:
  3080.         compile_prepareea(&map, insn_info[iip].dp->smode,
  3081.                   insn_info[iip].dp->sreg, 
  3082.                   insn_info[iip].dp->size, &realpc, current_addr,
  3083.                   eainfo, EA_LOAD, &pub, 1);
  3084.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  3085.                   insn_info[iip].dp->dreg, 
  3086.                   insn_info[iip].dp->size, &realpc, current_addr,
  3087.                   eainfo + 1, EA_STORE, &pub, 1);
  3088.  
  3089.         generate_possible_exit(&map, eainfo, iip, &pub);
  3090.         generate_possible_exit(&map, eainfo + 1, iip, &pub);
  3091.         
  3092.         srcreg = compile_fetchea(&map, eainfo + 0, &srcoffs);
  3093.         compile_storeea(&map, eainfo + 1, srcreg, srcoffs);
  3094.         cc_status = CC_TEST_REG;
  3095.         cc_reg = srcreg;
  3096.         cc_offset = srcoffs;
  3097.         cc_size = eainfo[0].size;
  3098.         
  3099.         break;
  3100.  
  3101.      case i_MOVEA:
  3102.         compile_prepareea(&map, insn_info[iip].dp->smode,
  3103.                   insn_info[iip].dp->sreg, 
  3104.                   insn_info[iip].dp->size, &realpc, current_addr,
  3105.                   eainfo, EA_LOAD, &pub, 1);
  3106.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  3107.                   insn_info[iip].dp->dreg,
  3108.                   sz_long, &realpc, current_addr,
  3109.                   eainfo + 1, EA_STORE, &pub, 1);
  3110.  
  3111.         generate_possible_exit(&map, eainfo, iip, &pub);
  3112.         
  3113.         srcreg = compile_fetchea(&map, eainfo, &srcoffs);
  3114.         srcreg2 = compile_extend_long(&map, srcreg, &srcoffs, eainfo[0].size);
  3115.         compile_unlock_reg(&map, srcreg);
  3116.         compile_storeea(&map, eainfo + 1, srcreg2, srcoffs);
  3117.  
  3118.         cc_status = 0;
  3119.         break;
  3120.  
  3121.      case i_EXG:
  3122.         compile_prepareea(&map, insn_info[iip].dp->smode,
  3123.                   insn_info[iip].dp->sreg,
  3124.                   sz_long, &realpc, current_addr,
  3125.                   eainfo, EA_LOAD|EA_STORE, &pub, 1);
  3126.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  3127.                   insn_info[iip].dp->dreg,
  3128.                   sz_long, &realpc, current_addr,
  3129.                   eainfo + 1, EA_LOAD|EA_STORE, &pub, 1);
  3130.  
  3131.         srcreg = compile_fetchea(&map, eainfo, &srcoffs);
  3132.         dstreg = compile_fetchea(&map, eainfo+1, &dstoffs);
  3133.         compile_unlock_reg(&map, srcreg);
  3134.         compile_storeea(&map, eainfo + 1, srcreg, srcoffs);
  3135.         compile_storeea(&map, eainfo, dstreg, dstoffs);
  3136.  
  3137.         cc_status = 0;
  3138.         break;
  3139.         
  3140.      case i_LINK:
  3141.         compile_prepareea(&map, insn_info[iip].dp->smode,
  3142.                   insn_info[iip].dp->sreg, 
  3143.                   sz_long, &realpc, current_addr,
  3144.                   eainfo, EA_LOAD|EA_STORE, &pub, 1);
  3145.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  3146.                   insn_info[iip].dp->dreg,
  3147.                   sz_long, &realpc, current_addr,
  3148.                   eainfo + 1, EA_LOAD, &pub, 1);
  3149.         compile_prepareea(&map, Apdi, 7, sz_long, &realpc, current_addr,
  3150.                   eainfo + 2, EA_STORE, &pub, 1);
  3151.  
  3152.         generate_possible_exit(&map, eainfo+2, iip, &pub);
  3153.  
  3154.         srcreg = compile_fetchea(&map, eainfo + 0, &srcoffs);
  3155.         dstreg = compile_fetchea(&map, eainfo + 1, &dstoffs);
  3156.         compile_storeea(&map, eainfo + 2, srcreg, srcoffs);
  3157.  
  3158.         compile_prepareea(&map, Areg, 7, sz_long, &realpc, current_addr,
  3159.                   eainfo + 3, EA_STORE, &pub, 1);
  3160.         srcreg = compile_fetchea(&map, eainfo + 3, &srcoffs);
  3161.         compile_storeea(&map, eainfo + 0, srcreg, srcoffs);
  3162.         /* @@@ 020 */
  3163.         compile_storeea(&map, eainfo + 3, srcreg, srcoffs+(WORD)dstoffs); 
  3164.         cc_status = 0;
  3165.         break;
  3166.                 
  3167.      case i_UNLK:
  3168.         compile_prepareea(&map, insn_info[iip].dp->smode,
  3169.                   insn_info[iip].dp->sreg, 
  3170.                   sz_long, &realpc, current_addr,
  3171.                   eainfo, EA_LOAD|EA_STORE, &pub, 1);
  3172.         compile_prepareea(&map, Aind,
  3173.                   insn_info[iip].dp->sreg, 
  3174.                   sz_long, &realpc, current_addr,
  3175.                   eainfo + 1, EA_LOAD, &pub, 1);
  3176.  
  3177.         generate_possible_exit(&map, eainfo+1, iip, &pub);
  3178.  
  3179.         compile_prepareea(&map, Areg, 7, sz_long, &realpc, current_addr,
  3180.                   eainfo + 3, EA_STORE, &pub, 1);
  3181.         srcreg = compile_fetchea(&map, eainfo + 1, &srcoffs);
  3182.         dstreg = compile_fetchea(&map, eainfo + 0, &dstoffs);
  3183.         compile_storeea(&map, eainfo + 0, srcreg, srcoffs);
  3184.         compile_storeea(&map, eainfo + 3, dstreg, dstoffs+4);
  3185.         cc_status = 0;        
  3186.         break;
  3187.  
  3188.      case i_OR:
  3189.      case i_AND:
  3190.      case i_EOR:
  3191.         compile_prepareea(&map, insn_info[iip].dp->smode,
  3192.                   insn_info[iip].dp->sreg, 
  3193.                   insn_info[iip].dp->size, &realpc, current_addr,
  3194.                   eainfo, EA_LOAD, &pub, 1);
  3195.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  3196.                   insn_info[iip].dp->dreg, 
  3197.                   insn_info[iip].dp->size, &realpc, current_addr,
  3198.                   eainfo + 1, EA_IN_REG | EA_LOAD | EA_STORE, &pub, 1);
  3199.  
  3200.         generate_possible_exit(&map, eainfo, iip, &pub);
  3201.         generate_possible_exit(&map, eainfo + 1, iip, &pub);
  3202.         
  3203.         szflag = insn_info[iip].dp->size == sz_byte ? 0 : 1;
  3204.         srcreg = compile_fetchea(&map, eainfo + 0, &srcoffs);
  3205.         dstreg = compile_fetchea(&map, eainfo + 1, &dstoffs);
  3206.         
  3207.         srcreg2 = compile_move_const_reg(&map, srcreg, &srcoffs, insn_info[iip].dp->size == sz_byte ? DATA_X86_REGS : 0);
  3208.         compile_unlock_reg(&map, srcreg);
  3209.         compile_offset_reg(&map, dstreg, dstoffs);
  3210.  
  3211.         compile_force_byteorder(&map, srcreg2, BO_NORMAL, 0);
  3212.         compile_force_byteorder(&map, dstreg, BO_NORMAL, 0);
  3213.  
  3214.         if (insn_info[iip].dp->size == sz_word)
  3215.         assemble(0x66);
  3216.         switch (insn_info[iip].dp->mnemo) {
  3217.          case i_AND: assemble(0x20+szflag); break;
  3218.          case i_EOR: assemble(0x30+szflag); break;
  3219.          case i_OR: assemble(0x08+szflag); break;
  3220.         }
  3221.         assemble(0xC0 + srcreg2*8 + dstreg);
  3222.         compile_storeea(&map, eainfo + 1, dstreg, 0);
  3223.         cc_status = CC_Z_FROM_86Z |CC_C_FROM_86C |CC_V_FROM_86V |CC_N_FROM_86N;
  3224.         break;
  3225.         
  3226.      case i_BTST:
  3227.      case i_BSET:
  3228.      case i_BCLR:
  3229.      case i_BCHG:
  3230.         compile_prepareea(&map, insn_info[iip].dp->smode,
  3231.                   insn_info[iip].dp->sreg, 
  3232.                   insn_info[iip].dp->size, &realpc, current_addr,
  3233.                   eainfo, EA_LOAD, &pub, 1);
  3234.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  3235.                   insn_info[iip].dp->dreg, 
  3236.                   insn_info[iip].dp->size, &realpc, current_addr,
  3237.                   eainfo + 1, 0, &pub, 1);
  3238.  
  3239.         generate_possible_exit(&map, eainfo, iip, &pub);
  3240.         generate_possible_exit(&map, eainfo + 1, iip, &pub);
  3241.  
  3242.         handle_bit_insns(&map, eainfo, eainfo + 1, insn_info[iip].dp->mnemo);
  3243.         break;
  3244.         
  3245.      case i_TST:
  3246.         compile_prepareea(&map, insn_info[iip].dp->smode,
  3247.                   insn_info[iip].dp->sreg, 
  3248.                   insn_info[iip].dp->size, &realpc, current_addr,
  3249.                   eainfo, EA_LOAD, &pub, 1);
  3250.  
  3251.         generate_possible_exit(&map, eainfo, iip, &pub);
  3252.         
  3253.         srcreg = compile_fetchea(&map, eainfo + 0, &srcoffs);
  3254.         cc_status = CC_TEST_REG;
  3255.         cc_reg = srcreg;
  3256.         cc_offset = srcoffs;
  3257.         cc_size = eainfo[0].size;
  3258.         break;
  3259.         
  3260.      case i_CLR:
  3261.         compile_prepareea(&map, insn_info[iip].dp->smode,
  3262.                   insn_info[iip].dp->sreg, 
  3263.                   insn_info[iip].dp->size, &realpc, current_addr,
  3264.                   eainfo, EA_STORE, &pub, 1);
  3265.  
  3266.         generate_possible_exit(&map, eainfo, iip, &pub);
  3267.         
  3268.         compile_storeea(&map, eainfo + 0, -2, 0);
  3269.  
  3270.         cc_status = CC_TEST_REG;
  3271.         cc_reg = -2;
  3272.         cc_offset = 0;
  3273.         cc_size = eainfo[0].size;
  3274.         break;
  3275.  
  3276.      case i_EXT:
  3277.         compile_prepareea(&map, insn_info[iip].dp->smode,
  3278.                   insn_info[iip].dp->sreg, 
  3279.                   insn_info[iip].dp->size == sz_long ? sz_word : sz_byte,
  3280.                   &realpc, current_addr,
  3281.                   eainfo, EA_LOAD|EA_STORE, &pub, 1);
  3282.         /* No exits - this is always a Dreg; fetchea will get it in a reg
  3283.          * without offset */
  3284.         srcreg = compile_fetchea(&map, eainfo + 0, &srcoffs);
  3285.  
  3286.         compile_force_byteorder(&map, srcreg, BO_NORMAL, 0);
  3287.  
  3288.         if (insn_info[iip].dp->size == sz_word)
  3289.         assemble(0x66);
  3290.         assemble(0x0F);
  3291.         if (insn_info[iip].dp->size == sz_long)
  3292.         assemble(0xBF);
  3293.         else
  3294.         assemble(0xBE);
  3295.         
  3296.         assemble(0xC0 + 9*srcreg);
  3297.         map.x86_dirty[srcreg] = 1;
  3298.  
  3299.         cc_status = CC_TEST_REG;
  3300.         cc_reg = srcreg;
  3301.         cc_offset = srcoffs;
  3302.         cc_size = eainfo[0].size;        
  3303.         break;
  3304.  
  3305.      case i_NOT:
  3306.      case i_NEG:
  3307.         szflag = insn_info[iip].dp->size == sz_byte ? 0 : 1;
  3308.  
  3309.         compile_prepareea(&map, insn_info[iip].dp->smode,
  3310.                   insn_info[iip].dp->sreg, 
  3311.                   insn_info[iip].dp->size,
  3312.                   &realpc, current_addr,
  3313.                   eainfo, EA_LOAD|EA_STORE, &pub, 1);
  3314.  
  3315.         generate_possible_exit(&map, eainfo, iip, &pub);
  3316.         
  3317.         srcreg = compile_fetchea(&map, eainfo + 0, &srcoffs);        
  3318.         srcreg2 = compile_move_const_reg(&map, srcreg, &srcoffs, insn_info[iip].dp->size == sz_byte ? DATA_X86_REGS : 0);
  3319.         compile_unlock_reg(&map, srcreg);
  3320.  
  3321.         compile_force_byteorder(&map, srcreg2, BO_NORMAL, 0);
  3322.  
  3323.         if (insn_info[iip].dp->size == sz_word)
  3324.         assemble(0x66);
  3325.         assemble(0xF6 + szflag);
  3326.         
  3327.         assemble(0xC0 + srcreg2 + 8*(insn_info[iip].dp->mnemo == i_NOT ? 2 : 3));
  3328.         compile_storeea(&map, eainfo, srcreg, 0);
  3329.  
  3330.         cc_status = CC_TEST_REG;
  3331.         cc_reg = srcreg;
  3332.         cc_offset = 0;
  3333.         cc_size = eainfo[0].size;        
  3334.         break;
  3335.  
  3336.      case i_SWAP:
  3337.         compile_prepareea(&map, insn_info[iip].dp->smode,
  3338.                   insn_info[iip].dp->sreg, sz_long,
  3339.                   &realpc, current_addr,
  3340.                   eainfo, EA_LOAD|EA_STORE, &pub, 1);
  3341.         /* No exits - this is always a Dreg; fetchea will get it in a reg
  3342.          * without offset */
  3343.         srcreg = compile_fetchea(&map, eainfo + 0, &srcoffs);
  3344.  
  3345.         compile_force_byteorder(&map, srcreg, BO_NORMAL, 0);
  3346.         /* roll $16, srcreg */
  3347.         assemble(0xC1); assemble(0xC0 + srcreg); assemble(16);
  3348.  
  3349.         map.x86_dirty[srcreg] = 1;
  3350.  
  3351.         cc_status = CC_TEST_REG;
  3352.         cc_reg = srcreg;
  3353.         cc_offset = srcoffs;
  3354.         cc_size = eainfo[0].size;        
  3355.         break;
  3356.         
  3357.      case i_LEA:
  3358.         compile_prepareea(&map, insn_info[iip].dp->smode,
  3359.                   insn_info[iip].dp->sreg, 
  3360.                   insn_info[iip].dp->size, &realpc, current_addr,
  3361.                   eainfo, 0, &pub, 1);
  3362.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  3363.                   insn_info[iip].dp->dreg,
  3364.                   sz_long, &realpc, current_addr,
  3365.                   eainfo + 1, EA_STORE, &pub, 1);
  3366.         compile_storeea(&map, eainfo + 1, eainfo[0].address_reg, 
  3367.                 eainfo[0].addr_const_off);
  3368.         cc_status = 0;
  3369.         break;
  3370.  
  3371.      case i_PEA:
  3372.         compile_prepareea(&map, insn_info[iip].dp->smode,
  3373.                   insn_info[iip].dp->sreg, 
  3374.                   insn_info[iip].dp->size, &realpc, current_addr,
  3375.                   eainfo, 0, &pub, 1);
  3376.         compile_prepareea(&map, Apdi, 7, sz_long, &realpc, current_addr,
  3377.                   eainfo + 1, EA_STORE, &pub, 1);
  3378.  
  3379.         generate_possible_exit(&map, eainfo+1, iip, &pub);
  3380.  
  3381.         compile_storeea(&map, eainfo + 1, eainfo[0].address_reg, 
  3382.                 eainfo[0].addr_const_off);
  3383.         cc_status = 0;
  3384.         break;
  3385.  
  3386.      case i_MVMEL:
  3387.         compile_prepareea(&map, insn_info[iip].dp->smode,
  3388.                   insn_info[iip].dp->sreg, 
  3389.                   sz_word, &realpc, current_addr,
  3390.                   eainfo, EA_LOAD, &pub, 1);
  3391.         sync_reg_cache(&map, 0);
  3392.         {
  3393.         /* Scratch 0 holds the registers while they are being moved
  3394.          * from/to memory. Scratch 1 points at regs.d. Scratch 2
  3395.          * points at the base addr in memory where to fetch data
  3396.          * from
  3397.          */
  3398.         int scratch0, scratch1, scratch2;
  3399.         UWORD mask = eainfo[0].data_const_off;
  3400.         int bits = count_bits(mask);
  3401.         int size = insn_info[iip].dp->size == sz_long ? 4 : 2;
  3402.         int i;
  3403.         UBYTE x86amode;
  3404.         ULONG current_offs = 0;
  3405.         
  3406.         /* !!! Note current_addr + 2 here! */
  3407.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  3408.                   insn_info[iip].dp->dreg,
  3409.                   insn_info[iip].dp->size, &realpc, current_addr + 2,
  3410.                   eainfo + 1, EA_LOAD, &pub, bits);
  3411.         
  3412.         generate_possible_exit(&map, eainfo + 1, iip, &pub);
  3413.  
  3414.         scratch0 = get_free_x86_register(&map, ADDRESS_X86_REGS);
  3415.         map.x86_locked[scratch0]++;
  3416.         scratch1 = get_free_x86_register(&map, ADDRESS_X86_REGS);
  3417.         map.x86_locked[scratch1]++;
  3418.         scratch2 = get_free_x86_register(&map, ADDRESS_X86_REGS);
  3419.         map.x86_locked[scratch2]++;
  3420.         compile_force_byteorder(&map, eainfo[1].address_reg, BO_NORMAL, 0);
  3421.         
  3422.         compile_lea_reg_with_offset(scratch1, -2, (ULONG)regs.d);
  3423.         compile_lea_reg_with_offset(scratch2, eainfo[1].address_reg,
  3424.                         (ULONG)(address_space + eainfo[1].addr_const_off));
  3425.  
  3426.         for (i = 0; i < 16; i++) {
  3427.             int r68k = i & 7;
  3428.             ULONG *regp = i < 8 ? regs.d : regs.a;
  3429.             int *cache68k = i < 8 ? map.dreg_map : map.areg_map;
  3430.             if (mask & 1 
  3431.             && (i < 8 
  3432.                 || insn_info[iip].dp->dmode != Aipi
  3433.                 || r68k != insn_info[iip].dp->dreg)) {
  3434.             int tmpr = cache68k[r68k];
  3435.             
  3436.             if (tmpr != -1) {
  3437.                 cache68k[r68k] = -1;
  3438.                 map.x86_cache_reg[tmpr] = -1;
  3439.             }
  3440.             compile_move_reg_from_mem_regoffs(scratch0, scratch2,
  3441.                               current_offs, insn_info[iip].dp->size);
  3442.             if (size == 2) {
  3443.                 assemble(0x66); /* rolw $8,scratch0 */
  3444.                 assemble(0xC1);
  3445.                 assemble(0xC0 + scratch0);
  3446.                 assemble(8);
  3447.                 assemble(0x0F); assemble(0xBF); /* extend */
  3448.                 assemble(0xC0 + 9*scratch0);
  3449.             } else {
  3450.                 assemble(0x0F); /* bswapl scratch0 */
  3451.                 assemble(0xC8 + scratch0);
  3452.             }
  3453.             compile_move_reg_to_mem_regoffs(scratch1, (char *)(regp + r68k) - (char *)regs.d,
  3454.                             scratch0, sz_long);
  3455.             }
  3456.             if (mask & 1)
  3457.             current_offs += size;
  3458.             mask >>= 1;
  3459.         }
  3460.         }
  3461.         cc_status = 0;
  3462.         break;
  3463.  
  3464.      case i_MVMLE:
  3465.         compile_prepareea(&map, insn_info[iip].dp->smode,
  3466.                   insn_info[iip].dp->sreg, 
  3467.                   sz_word, &realpc, current_addr,
  3468.                   eainfo, EA_LOAD, &pub, 1);
  3469.         sync_reg_cache(&map, 0);
  3470.         {
  3471.         int scratch0,scratch1,scratch2;
  3472.         UWORD mask = eainfo[0].data_const_off;
  3473.         int bits = count_bits(mask);
  3474.         int size = insn_info[iip].dp->size == sz_long ? 4 : 2;
  3475.         int i;
  3476.         UBYTE x86amode;
  3477.         ULONG current_offs = 0;
  3478.         int addrareg = get_and_lock_68k_reg(&map, insn_info[iip].dp->dreg, 
  3479.                             0, 0, 1);
  3480.         compile_force_byteorder(&map, addrareg, BO_NORMAL, 0);
  3481.         if (insn_info[iip].dp->dmode == Apdi)
  3482.             mask = bitswap(mask);
  3483.         /* !!! Note current_addr + 2 here! */
  3484.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  3485.                   insn_info[iip].dp->dreg,
  3486.                   insn_info[iip].dp->size, &realpc, current_addr + 2,
  3487.                   eainfo + 1, EA_STORE, &pub, bits);
  3488.         
  3489.         generate_possible_exit(&map, eainfo + 1, iip, &pub);
  3490.  
  3491.         scratch0 = get_free_x86_register(&map, ADDRESS_X86_REGS);
  3492.         map.x86_locked[scratch0]++;
  3493.         scratch1 = get_free_x86_register(&map, ADDRESS_X86_REGS);
  3494.         map.x86_locked[scratch1]++;
  3495.         scratch2 = get_free_x86_register(&map, ADDRESS_X86_REGS);
  3496.         map.x86_locked[scratch2]++;
  3497.  
  3498.         compile_force_byteorder(&map, eainfo[1].address_reg, BO_NORMAL, 0);
  3499.  
  3500.         compile_lea_reg_with_offset(scratch1, -2, (ULONG)regs.d);
  3501.         compile_lea_reg_with_offset(scratch2, eainfo[1].address_reg,
  3502.                         (ULONG)(address_space + eainfo[1].addr_const_off));
  3503.  
  3504.         for (i = 0; i < 16; i++) {
  3505.             int r68k = i & 7;
  3506.             ULONG *regp = i < 8 ? regs.d : regs.a;
  3507.             int *cache68k = i < 8 ? map.dreg_map : map.areg_map;
  3508.             if (mask & 1) {
  3509.             /* move from 68k reg */
  3510.             if (i < 8 || r68k != insn_info[iip].dp->dreg) {
  3511.                 compile_move_reg_from_mem_regoffs(scratch0, scratch1, (char *)(regp + r68k) - (char *)regs.d,
  3512.                                   sz_long);
  3513.             } else {
  3514.                 assemble(0x8B); assemble(0xC0 + 8*scratch0 + addrareg);
  3515.             }
  3516.  
  3517.             if (size == 2) {
  3518.                 assemble(0x66); /* rolw $8,scratch0 */
  3519.                 assemble(0xC1);
  3520.                 assemble(0xC0 + scratch0); assemble(8);
  3521.             } else {
  3522.                 assemble(0x0F); /* bswapl scratch0 */
  3523.                 assemble(0xC8 + scratch0);
  3524.             }
  3525.             compile_move_reg_to_mem_regoffs(scratch2, current_offs,
  3526.                             scratch0, insn_info[iip].dp->size);
  3527.             }
  3528.             if (mask & 1)
  3529.             current_offs += size;
  3530.             mask >>= 1;
  3531.         }
  3532.         }
  3533.         cc_status = 0;
  3534.         break;
  3535.  
  3536.      case i_ASL: case i_ASR: case i_LSL: case i_LSR: 
  3537.      case i_ROL: case i_ROR: case i_ROXL:case i_ROXR:
  3538.      case i_ASLW: case i_ASRW: case i_LSLW: case i_LSRW: 
  3539.      case i_ROLW: case i_RORW: case i_ROXLW:case i_ROXRW:
  3540.         if (do_rotshi) {
  3541.         handle_rotshi(&map, iip, realpc, current_addr);
  3542.         break;
  3543.         }
  3544.  
  3545.      default:
  3546.         generate_exit(&map, insn_info[iip].address); cc_status = 0;
  3547.         break;
  3548.     }
  3549.     if (insn_info[iip].ccuser_follows)
  3550.         cc_status_for_bcc = compile_flush_cc_cache(&map, cc_status, 
  3551.                    insn_info[iip].flags_live_at_end,
  3552.                    1, insn_info[iip+1].flags_live_at_end,
  3553.                    insn_info[iip+1].dp->cc);
  3554.     else
  3555.         cc_status_for_bcc = compile_flush_cc_cache(&map, cc_status, 
  3556.                    insn_info[iip].flags_live_at_end,
  3557.                    0, 0, 0);
  3558.  
  3559.     if (iip == current_bb->last_iip) {
  3560.         current_bb++;
  3561.     }
  3562.     }
  3563.     if (compile_failure)
  3564.     goto oops;
  3565.  
  3566.     /* Compile all exits that we prepared earlier */
  3567.     finish_exits();
  3568.     if (compile_failure)
  3569.     goto oops;
  3570.     finish_condjumps(last_iip);
  3571.     {
  3572.     int needed_len = compile_here() - hb->compile_start;
  3573.     int allocsize = (needed_len + PAGE_SUBUNIT - 1) & ~(PAGE_SUBUNIT-1);
  3574.     ULONG allocmask;
  3575.     int allocbits;
  3576.     
  3577.     allocbits = (allocsize >> SUBUNIT_ORDER);
  3578.     allocmask = (1 << allocbits) - 1;
  3579.     while ((allocmask & hb->page_allocmask) != allocmask)
  3580.         allocmask <<= 1;
  3581.     if ((hb->page_allocmask & ~allocmask) != 0 && !quiet_compile)
  3582.         fprintf(stderr, "Gaining some bits: %08lx\n", hb->page_allocmask & ~allocmask);
  3583.     hb->cpage->allocmask &= ~hb->page_allocmask;
  3584.     hb->page_allocmask = allocmask;
  3585.     hb->cpage->allocmask |= allocmask;
  3586.     }
  3587.     return 0;
  3588.     
  3589.     oops:
  3590.     if (1 || !quiet_compile)
  3591.     fprintf(stderr, "Compile failed!\n");
  3592.     hb->cpage->allocmask &= ~hb->page_allocmask;
  3593.     hb->cpage = NULL;
  3594.     hb->untranslatable = 1;
  3595.     {
  3596.     struct hash_entry *h = hb->he_first;
  3597.     
  3598.     do {
  3599.         h->execute = NULL;
  3600.         h = h->next_same_block;
  3601.     } while (h != hb->he_first);
  3602.     }
  3603.     return 1;
  3604. }
  3605.  
  3606. /*
  3607.  * Why do compilers always have to be so complicated? And I thought GCC was
  3608.  * a mess...
  3609.  */
  3610.  
  3611. #endif /* USE_COMPILER */
  3612.